GCC Code Coverage Report


Directory: ./
File: sql/rpl_replica.cc
Date: 2022-11-26 14:12:44
Exec Total Coverage
Lines: 4185 4575 91.5%
Branches: 5492 9825 55.9%

Line Branch Exec Source
1 /* Copyright (c) 2000, 2022, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /**
24 @addtogroup Replication
25 @{
26
27 @file sql/rpl_replica.cc
28
29 @brief Code to run the io thread and the sql thread on the
30 replication slave.
31 */
32
33 #include "sql/rpl_replica.h"
34
35 #include "my_config.h"
36
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <math.h>
40 #include <signal.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <time.h>
45
46 #include "include/compression.h"
47 #include "include/mutex_lock.h"
48 #include "mysql/components/services/bits/psi_bits.h"
49 #include "mysql/components/services/bits/psi_memory_bits.h"
50 #include "mysql/components/services/bits/psi_stage_bits.h"
51 #include "mysql/components/services/log_builtins.h"
52 #include "mysql/plugin.h"
53 #include "mysql/psi/mysql_cond.h"
54 #include "mysql/psi/mysql_mutex.h"
55 #include "mysql/status_var.h"
56 #include "sql/changestreams/apply/replication_thread_status.h"
57 #include "sql/rpl_channel_service_interface.h"
58 #ifdef HAVE_SYS_TIME_H
59 #include <sys/time.h>
60 #endif
61 #include <time.h>
62 #ifdef HAVE_UNISTD_H
63 #include <unistd.h>
64 #endif
65 #include <algorithm>
66 #include <atomic>
67 #include <deque>
68 #include <map>
69 #include <regex>
70 #include <string>
71 #include <utility>
72 #include <vector>
73
74 #include "errmsg.h" // CR_*
75 #include "lex_string.h"
76 #include "libbinlogevents/include/binlog_event.h"
77 #include "libbinlogevents/include/compression/iterator.h"
78 #include "libbinlogevents/include/control_events.h"
79 #include "libbinlogevents/include/debug_vars.h"
80 #include "m_ctype.h"
81 #include "m_string.h"
82 #include "mutex_lock.h" // MUTEX_LOCK
83 #include "my_bitmap.h" // MY_BITMAP
84 #include "my_byteorder.h"
85 #include "my_command.h"
86 #include "my_compiler.h"
87 #include "my_dbug.h"
88 #include "my_dir.h"
89 #include "my_io.h"
90 #include "my_loglevel.h"
91 #include "my_macros.h"
92 #include "my_sys.h"
93 #include "my_systime.h"
94 #include "my_thread_local.h" // thread_local_key_t
95 #include "mysql.h" // MYSQL
96 #include "mysql/psi/mysql_file.h"
97 #include "mysql/psi/mysql_memory.h"
98 #include "mysql/psi/mysql_thread.h"
99 #include "mysql/service_mysql_alloc.h"
100 #include "mysql/thread_type.h"
101 #include "mysql_com.h"
102 #include "mysqld_error.h"
103 #include "pfs_thread_provider.h"
104 #include "prealloced_array.h"
105 #include "sql-common/net_ns.h"
106 #include "sql/auth/auth_acls.h"
107 #include "sql/auth/sql_security_ctx.h"
108 #include "sql/auto_thd.h"
109 #include "sql/binlog.h"
110 #include "sql/binlog_reader.h"
111 #include "sql/clone_handler.h" // is_provisioning
112 #include "sql/current_thd.h"
113 #include "sql/debug_sync.h" // DEBUG_SYNC
114 #include "sql/derror.h" // ER_THD
115 #include "sql/dynamic_ids.h" // Server_ids
116 #include "sql/handler.h"
117 #include "sql/item.h"
118 #include "sql/log.h"
119 #include "sql/log_event.h" // Rotate_log_event
120 #include "sql/mdl.h"
121 #include "sql/mysqld.h" // ER
122 #include "sql/mysqld_thd_manager.h" // Global_THD_manager
123 #include "sql/protocol.h"
124 #include "sql/protocol_classic.h"
125 #include "sql/psi_memory_key.h"
126 #include "sql/query_options.h"
127 #include "sql/rpl_applier_reader.h"
128 #include "sql/rpl_async_conn_failover.h"
129 #include "sql/rpl_async_conn_failover_configuration_propagation.h"
130 #include "sql/rpl_filter.h"
131 #include "sql/rpl_group_replication.h"
132 #include "sql/rpl_gtid.h"
133 #include "sql/rpl_handler.h" // RUN_HOOK
134 #include "sql/rpl_info.h"
135 #include "sql/rpl_info_factory.h" // Rpl_info_factory
136 #include "sql/rpl_info_handler.h"
137 #include "sql/rpl_io_monitor.h"
138 #include "sql/rpl_mi.h"
139 #include "sql/rpl_msr.h" // Multisource_info
140 #include "sql/rpl_mta_submode.h"
141 #include "sql/rpl_replica_commit_order_manager.h" // Commit_order_manager
142 #include "sql/rpl_replica_until_options.h"
143 #include "sql/rpl_reporting.h"
144 #include "sql/rpl_rli.h" // Relay_log_info
145 #include "sql/rpl_rli_pdb.h" // Slave_worker
146 #include "sql/rpl_trx_boundary_parser.h"
147 #include "sql/rpl_utility.h"
148 #include "sql/sql_backup_lock.h" // is_instance_backup_locked
149 #include "sql/sql_class.h" // THD
150 #include "sql/sql_const.h"
151 #include "sql/sql_error.h"
152 #include "sql/sql_lex.h"
153 #include "sql/sql_list.h"
154 #include "sql/sql_parse.h" // execute_init_command
155 #include "sql/sql_plugin.h" // opt_plugin_dir_ptr
156 #include "sql/system_variables.h"
157 #include "sql/table.h"
158 #include "sql/transaction.h" // trans_begin
159 #include "sql/transaction_info.h"
160 #include "sql_common.h" // end_server
161 #include "sql_string.h"
162 #include "typelib.h"
163 #ifndef NDEBUG
164 #include "rpl_debug_points.h"
165 #endif
166
167 struct mysql_cond_t;
168 struct mysql_mutex_t;
169
170 using binary_log::checksum_crc32;
171 using binary_log::Log_event_header;
172 using std::max;
173 using std::min;
174
175 #define FLAGSTR(V, F) ((V) & (F) ? #F " " : "")
176
177 /*
178 a parameter of sql_slave_killed() to defer the killed status
179 */
180 #define SLAVE_WAIT_GROUP_DONE 60
181 bool use_slave_mask = false;
182 MY_BITMAP slave_error_mask;
183 char slave_skip_error_names[SHOW_VAR_FUNC_BUFF_SIZE];
184
185 char *replica_load_tmpdir = nullptr;
186 bool replicate_same_server_id;
187 ulonglong relay_log_space_limit = 0;
188
189 const char *relay_log_index = nullptr;
190 const char *relay_log_basename = nullptr;
191
192 /*
193 MTS load-ballancing parameter.
194 Max length of one MTS Worker queue. The value also determines the size
195 of Relay_log_info::gaq (see @c slave_start_workers()).
196 It can be set to any value in [1, ULONG_MAX - 1] range.
197 */
198 const ulong mts_slave_worker_queue_len_max = 16384;
199
200 /*
201 Statistics go to the error log every # of seconds when
202 --log_error_verbosity > 2
203 */
204 const long mts_online_stat_period = 60 * 2;
205
206 /*
207 MTS load-ballancing parameter.
208 Time unit in microsecs to sleep by MTS Coordinator to avoid extra thread
209 signalling in the case of Worker queues are close to be filled up.
210 */
211 const ulong mts_coordinator_basic_nap = 5;
212
213 /*
214 MTS load-ballancing parameter.
215 Percent of Worker queue size at which Worker is considered to become
216 hungry.
217
218 C enqueues --+ . underrun level
219 V "
220 +----------+-+------------------+--------------+
221 | empty |.|::::::::::::::::::|xxxxxxxxxxxxxx| ---> Worker dequeues
222 +----------+-+------------------+--------------+
223
224 Like in the above diagram enqueuing to the x-d area would indicate
225 actual underrruning by Worker.
226 */
227 const ulong mts_worker_underrun_level = 10;
228
229 /*
230 When slave thread exits, we need to remember the temporary tables so we
231 can re-use them on slave start.
232
233 TODO: move the vars below under Master_info
234 */
235
236 int disconnect_slave_event_count = 0, abort_slave_event_count = 0;
237
238 static thread_local Master_info *RPL_MASTER_INFO = nullptr;
239
240 /**
241 Encapsulates the messages and thread stages used for a specific call
242 to try_to_reconnect. Different Reconnect_messages objects may be
243 used by the caller of try_to_reconnect in order to make the errors
244 and stages include text that describes the reason for the reconnect.
245 */
246 struct Reconnect_messages {
247 /// Stage used while waiting to reconnect
248 PSI_stage_info &stage_waiting_to_reconnect;
249 /// Error reported in case the thread is killed while waiting
250 std::string error_killed_while_waiting;
251 /// Stage used while reconnecting
252 PSI_stage_info &stage_reconnecting;
253 /// Description of the condition that caused the thread to reconnect
254 std::string triggering_error;
255 /**
256 The string representation of the enum_server_command that had been
257 sent to the source before condition that caused the thread to
258 reconnect happened.
259 */
260 std::string triggering_command;
261 };
262
263 static Reconnect_messages reconnect_messages_after_failed_registration{
264 stage_replica_waiting_to_reconnect_after_failed_registration_on_source,
265 "Slave I/O thread killed while waiting to reconnect after a failed "
266 "registration on master",
267 stage_replica_reconnecting_after_failed_registration_on_source,
268 "failed registering on master, reconnecting to try again, "
269 "log '%s' at position %s",
270 "COM_REGISTER_SLAVE"};
271
272 static Reconnect_messages reconnect_messages_after_failed_dump{
273 stage_replica_waiting_to_reconnect_after_failed_binlog_dump_request,
274 "Slave I/O thread killed while retrying master dump",
275 stage_replica_reconnecting_after_failed_binlog_dump_request,
276 "failed dump request, reconnecting to try again, log '%s' at position "
277 "%s",
278 "COM_BINLOG_DUMP"};
279
280 static Reconnect_messages reconnect_messages_after_failed_event_read{
281 stage_replica_waiting_to_reconnect_after_failed_event_read,
282 "Slave I/O thread killed while waiting to reconnect after a failed read",
283 stage_replica_reconnecting_after_failed_event_read,
284 "Slave I/O thread: Failed reading log event, reconnecting to retry, "
285 "log '%s' at position %s",
286 ""};
287
288 enum enum_slave_apply_event_and_update_pos_retval {
289 SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK = 0,
290 SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPLY_ERROR = 1,
291 SLAVE_APPLY_EVENT_AND_UPDATE_POS_UPDATE_POS_ERROR = 2,
292 SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPEND_JOB_ERROR = 3,
293 SLAVE_APPLY_EVENT_RETRY = 4,
294 SLAVE_APPLY_EVENT_UNTIL_REACHED = 5,
295 SLAVE_APPLY_EVENT_AND_UPDATE_POS_MAX
296 };
297
298 static int process_io_rotate(Master_info *mi, Rotate_log_event *rev);
299 static bool wait_for_relay_log_space(Relay_log_info *rli);
300 static inline bool io_slave_killed(THD *thd, Master_info *mi);
301 static inline bool monitor_io_replica_killed(THD *thd, Master_info *mi);
302 static inline bool is_autocommit_off_and_infotables(THD *thd);
303 static void print_replica_skip_errors(void);
304 static int safe_connect(THD *thd, MYSQL *mysql, Master_info *mi,
305 const std::string &host = std::string(),
306 const uint port = 0);
307 static int safe_reconnect(THD *thd, MYSQL *mysql, Master_info *mi,
308 bool suppress_warnings,
309 const std::string &host = std::string(),
310 const uint port = 0);
311 static int get_master_version_and_clock(MYSQL *mysql, Master_info *mi);
312 static int get_master_uuid(MYSQL *mysql, Master_info *mi);
313 int io_thread_init_commands(MYSQL *mysql, Master_info *mi);
314 static int terminate_slave_thread(THD *thd, mysql_mutex_t *term_lock,
315 mysql_cond_t *term_cond,
316 std::atomic<uint> *slave_running,
317 ulong *stop_wait_timeout, bool need_lock_term,
318 bool force = false);
319 static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info);
320 static int mts_event_coord_cmp(LOG_POS_COORD *id1, LOG_POS_COORD *id2);
321
322 static int check_slave_sql_config_conflict(const Relay_log_info *rli);
323 static void group_replication_cleanup_after_clone();
324
325 static void check_replica_configuration_restrictions();
326 static bool check_replica_configuration_errors(Master_info *mi,
327 int thread_mask);
328 /*
329 Applier thread InnoDB priority.
330 When two transactions conflict inside InnoDB, the one with
331 greater priority wins.
332
333 @param thd Thread handler for slave
334 @param priority Thread priority
335 */
336 51712 static void set_thd_tx_priority(THD *thd, int priority) {
337
1/2
✓ Branch 0 taken 51712 times.
✗ Branch 1 not taken.
51712 DBUG_TRACE;
338
3/4
✓ Branch 0 taken 41274 times.
✓ Branch 1 taken 10438 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 41274 times.
51712 assert(thd->system_thread == SYSTEM_THREAD_SLAVE_SQL ||
339 thd->system_thread == SYSTEM_THREAD_SLAVE_WORKER);
340
341 51712 thd->thd_tx_priority = priority;
342
3/4
✓ Branch 0 taken 51712 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 51702 times.
51712 DBUG_EXECUTE_IF("dbug_set_high_prio_sql_thread",
343 { thd->thd_tx_priority = 1; });
344 51712 }
345
346 /**
347 Set for the thread options about the memory and size limits when
348 transactions collect write sets.
349
350 @param thd Thread handler
351 @param ignore_limit if the memory limits should be ignored
352 @param allow_drop_write_set if this thread does not require WS to always be
353 logged
354 */
355 51712 static void set_thd_write_set_options(THD *thd, bool ignore_limit,
356 bool allow_drop_write_set) {
357
1/2
✓ Branch 0 taken 51712 times.
✗ Branch 1 not taken.
51712 DBUG_TRACE;
358 thd->get_transaction()
359 ->get_transaction_write_set_ctx()
360
1/2
✓ Branch 0 taken 51712 times.
✗ Branch 1 not taken.
51712 ->set_local_ignore_write_set_memory_limit(ignore_limit);
361 thd->get_transaction()
362 ->get_transaction_write_set_ctx()
363
1/2
✓ Branch 0 taken 51712 times.
✗ Branch 1 not taken.
51712 ->set_local_allow_drop_write_set(allow_drop_write_set);
364 51712 }
365
366 /*
367 Function to set the slave's max_allowed_packet based on the value
368 of replica_max_allowed_packet.
369
370 @in_param thd Thread handler for slave
371 @in_param mysql MySQL connection handle
372 */
373
374 8173 static void set_replica_max_allowed_packet(THD *thd, MYSQL *mysql) {
375
1/2
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
8173 DBUG_TRACE;
376 // thd and mysql must be valid
377
2/4
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8173 times.
✗ Branch 3 not taken.
8173 assert(thd && mysql);
378
379 8173 thd->variables.max_allowed_packet = replica_max_allowed_packet;
380 /*
381 Adding MAX_LOG_EVENT_HEADER_LEN to the max_packet_size on the I/O
382 thread and the mysql->option max_allowed_packet, since a
383 replication event can become this much larger than
384 the corresponding packet (query) sent from client to master.
385 */
386
2/4
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8173 times.
✗ Branch 3 not taken.
8173 thd->get_protocol_classic()->set_max_packet_size(replica_max_allowed_packet +
387 MAX_LOG_EVENT_HEADER);
388 /*
389 Skipping the setting of mysql->net.max_packet size to slave
390 max_allowed_packet since this is done during mysql_real_connect.
391 */
392 8173 mysql->options.max_allowed_packet =
393 8173 replica_max_allowed_packet + MAX_LOG_EVENT_HEADER;
394 8173 }
395
396 #ifdef HAVE_PSI_INTERFACE
397
398 static PSI_memory_key key_memory_rli_mta_coor;
399
400 static PSI_thread_key key_thread_replica_io, key_thread_replica_sql,
401 key_thread_replica_worker, key_thread_replica_monitor_io;
402
403 static PSI_thread_info all_slave_threads[] = {
404 {&key_thread_replica_io, "replica_io", "rpl_rca_io", PSI_FLAG_THREAD_SYSTEM,
405 0, PSI_DOCUMENT_ME},
406 {&key_thread_replica_sql, "replica_sql", "rpl_rca_sql",
407 PSI_FLAG_THREAD_SYSTEM, 0, PSI_DOCUMENT_ME},
408 {&key_thread_replica_worker, "replica_worker", "rpl_rca_wkr",
409 PSI_FLAG_THREAD_SYSTEM, 0, PSI_DOCUMENT_ME},
410 {&key_thread_replica_monitor_io, "replica_monitor", "rpl_rca_mon",
411 PSI_FLAG_SINGLETON | PSI_FLAG_THREAD_SYSTEM, 0, PSI_DOCUMENT_ME}};
412
413 static PSI_memory_info all_slave_memory[] = {{&key_memory_rli_mta_coor,
414 "Relay_log_info::mta_coor", 0, 0,
415 PSI_DOCUMENT_ME}};
416
417 11397 static void init_replica_psi_keys(void) {
418 11397 const char *category = "sql";
419 int count;
420
421 11397 count = static_cast<int>(array_elements(all_slave_threads));
422 11397 mysql_thread_register(category, all_slave_threads, count);
423
424 11397 count = static_cast<int>(array_elements(all_slave_memory));
425 11397 mysql_memory_register(category, all_slave_memory, count);
426 11397 }
427 #endif /* HAVE_PSI_INTERFACE */
428
429 /* Initialize slave structures */
430
431 11397 int init_replica() {
432
1/2
✓ Branch 0 taken 11397 times.
✗ Branch 1 not taken.
11397 DBUG_TRACE;
433 11397 int error = 0;
434 11397 int thread_mask = SLAVE_SQL | SLAVE_IO;
435
436 #ifdef HAVE_PSI_INTERFACE
437
1/2
✓ Branch 0 taken 11397 times.
✗ Branch 1 not taken.
11397 init_replica_psi_keys();
438 #endif
439
440 /*
441 This is called when mysqld starts. Before client connections are
442 accepted. However bootstrap may conflict with us if it does START SLAVE.
443 So it's safer to take the lock.
444 */
445
1/2
✓ Branch 0 taken 11397 times.
✗ Branch 1 not taken.
11397 channel_map.wrlock();
446
447 11397 RPL_MASTER_INFO = nullptr;
448
449 /*
450 Create slave info objects by reading repositories of individual
451 channels and add them into channel_map
452 */
453
3/4
✓ Branch 0 taken 11394 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 11385 times.
11397 if ((error = Rpl_info_factory::create_slave_info_objects(
454 opt_mi_repository_id, opt_rli_repository_id, thread_mask,
455 &channel_map)))
456
8/16
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 9 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 9 times.
✗ Branch 15 not taken.
9 LogErr(ERROR_LEVEL,
457 ER_RPL_SLAVE_FAILED_TO_CREATE_OR_RECOVER_INFO_REPOSITORIES);
458
459
1/2
✓ Branch 0 taken 11394 times.
✗ Branch 1 not taken.
11394 group_replication_cleanup_after_clone();
460
461 #ifndef NDEBUG
462 /* @todo: Print it for all the channels */
463 {
464 Master_info *default_mi;
465
1/2
✓ Branch 0 taken 11394 times.
✗ Branch 1 not taken.
11394 default_mi = channel_map.get_default_channel_mi();
466
3/4
✓ Branch 0 taken 11390 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 11390 times.
✗ Branch 3 not taken.
11394 if (default_mi && default_mi->rli) {
467
3/8
✓ Branch 0 taken 11390 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11390 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11390 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
11390 DBUG_PRINT("info",
468 ("init group master %s %lu group relay %s %lu event %s %lu\n",
469 default_mi->rli->get_group_master_log_name(),
470 (ulong)default_mi->rli->get_group_master_log_pos(),
471 default_mi->rli->get_group_relay_log_name(),
472 (ulong)default_mi->rli->get_group_relay_log_pos(),
473 default_mi->rli->get_event_relay_log_name(),
474 (ulong)default_mi->rli->get_event_relay_log_pos()));
475 }
476 }
477 #endif
478
479
1/2
✓ Branch 0 taken 11394 times.
✗ Branch 1 not taken.
11394 check_replica_configuration_restrictions();
480
481
2/4
✓ Branch 0 taken 11394 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11394 times.
11394 if (check_slave_sql_config_conflict(nullptr)) {
482 error = 1;
483 goto err;
484 }
485
486 /*
487 Loop through the channel_map and start slave threads for each channel.
488 */
489
2/2
✓ Branch 0 taken 3118 times.
✓ Branch 1 taken 8276 times.
11394 if (!opt_skip_replica_start) {
490
4/6
✓ Branch 0 taken 8276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16576 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8300 times.
✓ Branch 5 taken 8276 times.
16576 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
491 8300 it++) {
492 8300 Master_info *mi = it->second;
493
494 /* If server id is not set, start_slave_thread() will say it */
495
6/6
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 8215 times.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 79 times.
✓ Branch 5 taken 8221 times.
8300 if (Master_info::is_configured(mi) && mi->rli->inited) {
496 /* same as in start_slave() cache the global var values into rli's
497 * members */
498 79 mi->rli->opt_replica_parallel_workers =
499 opt_mts_replica_parallel_workers;
500 79 mi->rli->checkpoint_group = opt_mta_checkpoint_group;
501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (mts_parallel_option == MTS_PARALLEL_TYPE_DB_NAME)
502 mi->rli->channel_mts_submode = MTS_PARALLEL_TYPE_DB_NAME;
503 else
504 79 mi->rli->channel_mts_submode = MTS_PARALLEL_TYPE_LOGICAL_CLOCK;
505
506
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 78 times.
79 if (mi->is_source_connection_auto_failover())
507 1 thread_mask |= SLAVE_MONITOR;
508
509
2/4
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 79 times.
79 if (start_slave_threads(true /*need_lock_slave=true*/,
510 false /*wait_for_start=false*/, mi,
511 thread_mask)) {
512 LogErr(ERROR_LEVEL, ER_FAILED_TO_START_SLAVE_THREAD,
513 mi->get_channel());
514 }
515 } else {
516
8/16
✓ Branch 0 taken 8221 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8221 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8221 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8221 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8221 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8221 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 8221 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 8221 times.
✗ Branch 15 not taken.
8221 LogErr(INFORMATION_LEVEL, ER_FAILED_TO_START_SLAVE_THREAD,
517 mi->get_channel());
518 }
519 }
520 }
521
522 3118 err:
523
524
1/2
✓ Branch 0 taken 11394 times.
✗ Branch 1 not taken.
11394 channel_map.unlock();
525
10/18
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11385 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 9 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 9 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 9 times.
✗ Branch 17 not taken.
11394 if (error) LogErr(INFORMATION_LEVEL, ER_SLAVE_NOT_STARTED_ON_SOME_CHANNELS);
526
527 11394 return error;
528 11394 }
529
530 /**
531 Function to start a slave for all channels.
532 Used in Multisource replication.
533 @param[in] thd THD object of the client.
534
535 @retval false success
536 @retval true error
537
538 @todo It is good to continue to start other channels
539 when a slave start failed for other channels.
540
541 @todo The problem with the below code is if the slave is already
542 stared, we would have multiple warnings
543 "Slave was already running" for each channel.
544 A nice warning message would be to add
545 "Slave for channel '%s' was already running"
546 but error messages are in different languages and cannot be tampered
547 with so, we have to handle it case by case basis, whether
548 only default channel exists or not and properly continue with
549 starting other channels if one channel fails clearly giving
550 an error message by displaying failed channels.
551 */
552 7094 bool start_slave(THD *thd) {
553
1/2
✓ Branch 0 taken 7094 times.
✗ Branch 1 not taken.
7094 DBUG_TRACE;
554 Master_info *mi;
555 7094 bool channel_configured, error = false;
556
557
3/4
✓ Branch 0 taken 7094 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7003 times.
✓ Branch 3 taken 91 times.
7094 if (channel_map.get_num_instances() == 1) {
558
1/2
✓ Branch 0 taken 7003 times.
✗ Branch 1 not taken.
7003 mi = channel_map.get_default_channel_mi();
559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7003 times.
7003 assert(mi);
560
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 6958 times.
6997 if (start_slave(thd, &thd->lex->slave_connection, &thd->lex->mi,
561
1/2
✓ Branch 0 taken 6997 times.
✗ Branch 1 not taken.
7003 thd->lex->slave_thd_opt, mi, true))
562 39 return true;
563 } else {
564 /*
565 Users cannot start more than one channel's applier thread
566 if sql_replica_skip_counter > 0. It throws an error to the session.
567 */
568
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 mysql_mutex_lock(&LOCK_sql_replica_skip_counter);
569 /* sql_replica_skip_counter > 0 && !(START SLAVE IO_THREAD) */
570
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
91 if (sql_replica_skip_counter > 0 && !(thd->lex->slave_thd_opt & SLAVE_IO)) {
571
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_CHANNEL_SQL_SKIP_COUNTER, MYF(0));
572
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 mysql_mutex_unlock(&LOCK_sql_replica_skip_counter);
573 2 return true;
574 }
575
1/2
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
89 mysql_mutex_unlock(&LOCK_sql_replica_skip_counter);
576
577
4/6
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 342 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 253 times.
✓ Branch 5 taken 89 times.
342 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
578 253 it++) {
579 253 mi = it->second;
580
581 253 channel_configured =
582 253 mi && // Master_info exists
583
3/4
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 184 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
253 (mi->inited || mi->reset) // It is inited or was reset
584
2/4
✓ Branch 0 taken 253 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 184 times.
✗ Branch 3 not taken.
506 && mi->host[0]; // host is set
585
586
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 69 times.
253 if (channel_configured) {
587
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 181 times.
184 if (start_slave(thd, &thd->lex->slave_connection, &thd->lex->mi,
588
1/2
✓ Branch 0 taken 184 times.
✗ Branch 1 not taken.
184 thd->lex->slave_thd_opt, mi, true)) {
589
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_CANT_START_SLAVE_FOR_CHANNEL,
590 mi->get_channel());
591 3 error = true;
592 }
593 }
594 }
595 }
596
2/2
✓ Branch 0 taken 7044 times.
✓ Branch 1 taken 3 times.
7047 if (!error) {
597 /* no error */
598
1/2
✓ Branch 0 taken 7044 times.
✗ Branch 1 not taken.
7044 my_ok(thd);
599 }
600 7047 return error;
601 7088 }
602
603 /**
604 Function to stop a slave for all channels.
605 Used in Multisource replication.
606 @param[in] thd THD object of the client.
607
608 @retval 0 success
609 @retval 1 error
610
611 @todo It is good to continue to stop other channels
612 when a slave start failed for other channels.
613 */
614 5786 int stop_slave(THD *thd) {
615
1/2
✓ Branch 0 taken 5786 times.
✗ Branch 1 not taken.
5786 DBUG_TRACE;
616 5786 bool push_temp_table_warning = true;
617 5786 Master_info *mi = nullptr;
618 5786 int error = 0;
619
620
3/4
✓ Branch 0 taken 5786 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5720 times.
✓ Branch 3 taken 66 times.
5786 if (channel_map.get_num_instances() == 1) {
621
1/2
✓ Branch 0 taken 5720 times.
✗ Branch 1 not taken.
5720 mi = channel_map.get_default_channel_mi();
622
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5720 times.
5720 assert(!strcmp(mi->get_channel(), channel_map.get_default_channel()));
624
625
1/2
✓ Branch 0 taken 5720 times.
✗ Branch 1 not taken.
5720 error = stop_slave(thd, mi, true, false /*for_one_channel*/,
626 &push_temp_table_warning);
627 } else {
628
4/6
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 292 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 226 times.
✓ Branch 5 taken 66 times.
292 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
629 226 it++) {
630 226 mi = it->second;
631
632
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 53 times.
226 if (Master_info::is_configured(mi)) {
633
2/4
✓ Branch 0 taken 173 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 173 times.
173 if (stop_slave(thd, mi, true, false /*for_one_channel*/,
634 &push_temp_table_warning)) {
635 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_CANT_STOP_SLAVE_FOR_CHANNEL,
636 mi->get_channel());
637 error = 1;
638 }
639 }
640 }
641 }
642
643
2/2
✓ Branch 0 taken 5785 times.
✓ Branch 1 taken 1 times.
5786 if (!error) {
644 /* no error */
645
1/2
✓ Branch 0 taken 5785 times.
✗ Branch 1 not taken.
5785 my_ok(thd);
646 }
647
648 5786 return error;
649 5786 }
650
651 /**
652 Entry point to the START SLAVE command. The function
653 decides to start replication threads on several channels
654 or a single given channel.
655
656 @param[in] thd the client thread carrying the command.
657
658 @retval false ok
659 @retval true not ok.
660 */
661 7487 bool start_slave_cmd(THD *thd) {
662
1/2
✓ Branch 0 taken 7487 times.
✗ Branch 1 not taken.
7487 DBUG_TRACE;
663
664 Master_info *mi;
665 7487 LEX *lex = thd->lex;
666 7487 bool res = true; /* default, an error */
667
668
2/4
✓ Branch 0 taken 7487 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7487 times.
✗ Branch 3 not taken.
7487 DEBUG_SYNC(thd, "begin_start_replica");
669
670
1/2
✓ Branch 0 taken 7487 times.
✗ Branch 1 not taken.
7487 channel_map.wrlock();
671
672
2/4
✓ Branch 0 taken 7487 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7487 times.
✗ Branch 3 not taken.
7487 DEBUG_SYNC(thd, "after_locking_channel_map_in_start_replica");
673
674
3/4
✓ Branch 0 taken 7487 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 7480 times.
7487 if (!is_slave_configured()) {
675
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_error(ER_SLAVE_CONFIGURATION, MYF(0));
676 7 goto err;
677 }
678
679
2/2
✓ Branch 0 taken 7096 times.
✓ Branch 1 taken 384 times.
7480 if (!lex->mi.for_channel) {
680 /*
681 If slave_until options are provided when multiple channels exist
682 without explicitly providing FOR CHANNEL clause, error out.
683 */
684
7/8
✓ Branch 0 taken 119 times.
✓ Branch 1 taken 6977 times.
✓ Branch 2 taken 119 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 117 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 7094 times.
7096 if (lex->mi.slave_until && channel_map.get_num_instances() > 1) {
685
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_MULTIPLE_CHANNELS_CMD, MYF(0));
686 2 goto err;
687 }
688
689
1/2
✓ Branch 0 taken 7088 times.
✗ Branch 1 not taken.
7094 res = start_slave(thd);
690 } else {
691
1/2
✓ Branch 0 taken 384 times.
✗ Branch 1 not taken.
384 mi = channel_map.get_mi(lex->mi.channel);
692
693 /*
694 If the channel being used is a group replication channel we need to
695 disable this command here as, in some cases, group replication does not
696 support them.
697
698 For channel group_replication_applier we disable START SLAVE [IO_THREAD]
699 command.
700
701 For channel group_replication_recovery we disable START SLAVE command
702 and its two thread variants.
703 */
704 758 if (mi &&
705
7/8
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 374 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 67 times.
✓ Branch 5 taken 307 times.
✓ Branch 6 taken 17 times.
✓ Branch 7 taken 367 times.
451 channel_map.is_group_replication_channel_name(mi->get_channel()) &&
706
4/4
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 7 times.
67 ((!thd->lex->slave_thd_opt || (thd->lex->slave_thd_opt & SLAVE_IO)) ||
707
3/4
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 50 times.
55 (!(channel_map.is_group_replication_channel_name(mi->get_channel(),
708 5 true)) &&
709
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 (thd->lex->slave_thd_opt & SLAVE_SQL)))) {
710 17 const char *command = "START SLAVE FOR CHANNEL";
711
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 10 times.
17 if (thd->lex->slave_thd_opt & SLAVE_IO)
712 7 command = "START SLAVE IO_THREAD FOR CHANNEL";
713
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 else if (thd->lex->slave_thd_opt & SLAVE_SQL)
714 5 command = "START SLAVE SQL_THREAD FOR CHANNEL";
715
716
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0), command,
717 mi->get_channel(), command);
718
719 17 goto err;
720 }
721
722
2/2
✓ Branch 0 taken 357 times.
✓ Branch 1 taken 10 times.
367 if (mi)
723 357 res = start_slave(thd, &thd->lex->slave_connection, &thd->lex->mi,
724
1/2
✓ Branch 0 taken 357 times.
✗ Branch 1 not taken.
357 thd->lex->slave_thd_opt, mi, true);
725
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 else if (strcmp(channel_map.get_default_channel(), lex->mi.channel))
726
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 my_error(ER_SLAVE_CHANNEL_DOES_NOT_EXIST, MYF(0), lex->mi.channel);
727
728
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 351 times.
✓ Branch 2 taken 351 times.
✗ Branch 3 not taken.
367 if (!res) my_ok(thd);
729 }
730 16 err:
731
1/2
✓ Branch 0 taken 7481 times.
✗ Branch 1 not taken.
7481 channel_map.unlock();
732 7481 return res;
733 7481 }
734
735 /**
736 Entry point for the STOP SLAVE command. This function stops replication
737 threads for all channels or a single channel based on the command
738 options supplied.
739
740 @param[in] thd the client thread.
741
742 @retval false ok
743 @retval true not ok.
744 */
745 6262 bool stop_slave_cmd(THD *thd) {
746
1/2
✓ Branch 0 taken 6262 times.
✗ Branch 1 not taken.
6262 DBUG_TRACE;
747
748 Master_info *mi;
749 6262 bool push_temp_table_warning = true;
750 6262 LEX *lex = thd->lex;
751 6262 bool res = true; /*default, an error */
752
753
1/2
✓ Branch 0 taken 6262 times.
✗ Branch 1 not taken.
6262 channel_map.rdlock();
754
755
3/4
✓ Branch 0 taken 6262 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6261 times.
6262 if (!is_slave_configured()) {
756
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SLAVE_CONFIGURATION, MYF(0));
757
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 channel_map.unlock();
758 1 return true;
759 }
760
761
1/2
✓ Branch 0 taken 6261 times.
✗ Branch 1 not taken.
6261 MDL_lock_guard backup_sentry{thd};
762 /* During provisioning we stop slave after acquiring backup lock. */
763
4/4
✓ Branch 0 taken 6201 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 5605 times.
✓ Branch 3 taken 656 times.
12462 if (!Clone_handler::is_provisioning() &&
764
4/4
✓ Branch 0 taken 1331 times.
✓ Branch 1 taken 4870 times.
✓ Branch 2 taken 735 times.
✓ Branch 3 taken 596 times.
6201 (!thd->lex->slave_thd_opt || (thd->lex->slave_thd_opt & SLAVE_SQL))) {
765
3/4
✓ Branch 0 taken 5605 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 5597 times.
5605 if (backup_sentry.lock(MDL_key::BACKUP_LOCK, MDL_INTENTION_EXCLUSIVE)) {
766
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 my_error(ER_RPL_CANT_STOP_SLAVE_WHILE_LOCKED_BACKUP, MYF(0));
767
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 channel_map.unlock();
768 8 return true;
769 }
770 }
771
772
2/2
✓ Branch 0 taken 5786 times.
✓ Branch 1 taken 467 times.
6253 if (!lex->mi.for_channel)
773
1/2
✓ Branch 0 taken 5786 times.
✗ Branch 1 not taken.
5786 res = stop_slave(thd);
774 else {
775
1/2
✓ Branch 0 taken 467 times.
✗ Branch 1 not taken.
467 mi = channel_map.get_mi(lex->mi.channel);
776
777 /*
778 If the channel being used is a group replication channel we need to
779 disable this command here as, in some cases, group replication does not
780 support them.
781
782 For channel group_replication_applier we disable STOP SLAVE [IO_THREAD]
783 command.
784
785 For channel group_replication_recovery we disable STOP SLAVE command
786 and its two thread variants.
787 */
788 925 if (mi &&
789
7/8
✓ Branch 0 taken 458 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 458 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 92 times.
✓ Branch 5 taken 366 times.
✓ Branch 6 taken 13 times.
✓ Branch 7 taken 454 times.
559 channel_map.is_group_replication_channel_name(mi->get_channel()) &&
790
4/4
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 82 times.
✓ Branch 3 taken 5 times.
92 ((!thd->lex->slave_thd_opt || (thd->lex->slave_thd_opt & SLAVE_IO)) ||
791
3/4
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 79 times.
82 (!(channel_map.is_group_replication_channel_name(mi->get_channel(),
792 3 true)) &&
793
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 (thd->lex->slave_thd_opt & SLAVE_SQL)))) {
794 13 const char *command = "STOP SLAVE FOR CHANNEL";
795
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
13 if (thd->lex->slave_thd_opt & SLAVE_IO)
796 5 command = "STOP SLAVE IO_THREAD FOR CHANNEL";
797
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 else if (thd->lex->slave_thd_opt & SLAVE_SQL)
798 3 command = "STOP SLAVE SQL_THREAD FOR CHANNEL";
799
800
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0), command,
801 mi->get_channel(), command);
802
803
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 channel_map.unlock();
804 13 return true;
805 }
806
807
2/2
✓ Branch 0 taken 445 times.
✓ Branch 1 taken 9 times.
454 if (mi)
808
1/2
✓ Branch 0 taken 445 times.
✗ Branch 1 not taken.
445 res = stop_slave(thd, mi, true /*net report */, true /*for_one_channel*/,
809 &push_temp_table_warning);
810
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 else if (strcmp(channel_map.get_default_channel(), lex->mi.channel))
811
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_error(ER_SLAVE_CHANNEL_DOES_NOT_EXIST, MYF(0), lex->mi.channel);
812 }
813
814
1/2
✓ Branch 0 taken 6240 times.
✗ Branch 1 not taken.
6240 channel_map.unlock();
815
816
4/6
✓ Branch 0 taken 6240 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6238 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
6240 DBUG_EXECUTE_IF("stop_replica_dont_release_backup_lock", {
817 rpl_replica_debug_point(DBUG_RPL_S_STOP_SLAVE_BACKUP_LOCK, thd);
818 });
819
820 6240 return res;
821 6262 }
822
823 enum enum_read_rotate_from_relay_log_status {
824 FOUND_ROTATE,
825 NOT_FOUND_ROTATE,
826 ERROR
827 };
828
829 /**
830 Parse the given relay log and identify the rotate event from the master.
831 Ignore the Format description event, Previous_gtid log event, ignorable
832 event and Stop event within the relay log as they are generated by slave.
833 When a rotate event is found check if it is a rotate that is originated from
834 the master based on the server_id. Ignore the event if the rotate is from
835 slave or if it is a fake rotate event. If any other events are encountered
836 apart from the above events generate an error. From the rotate event
837 extract the master's binary log name and position.
838
839 @param filename
840 Relay log name which needs to be parsed.
841
842 @param[out] master_log_file
843 Set the master_log_file to the log file name that is extracted from
844 rotate event. The master_log_file should contain string of len
845 FN_REFLEN.
846
847 @param[out] master_log_pos
848 Set the master_log_pos to the log position extracted from rotate
849 event.
850
851 @retval FOUND_ROTATE: When rotate event is found in the relay log
852 @retval NOT_FOUND_ROTATE: When rotate event is not found in the relay log
853 @retval ERROR: On error
854 */
855 20 static enum_read_rotate_from_relay_log_status read_rotate_from_relay_log(
856 char *filename, char *master_log_file, my_off_t *master_log_pos) {
857
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 DBUG_TRACE;
858
859
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 Relaylog_file_reader relaylog_file_reader(opt_replica_sql_verify_checksum);
860
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
20 if (relaylog_file_reader.open(filename)) {
861 LogErr(ERROR_LEVEL, ER_RPL_RECOVERY_ERROR,
862 relaylog_file_reader.get_error_str());
863 return ERROR;
864 }
865
866 20 Log_event *ev = nullptr;
867 20 bool done = false;
868 20 enum_read_rotate_from_relay_log_status ret = NOT_FOUND_ROTATE;
869
7/8
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 71 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 55 times.
✓ Branch 5 taken 16 times.
✓ Branch 6 taken 55 times.
✓ Branch 7 taken 20 times.
75 while (!done && (ev = relaylog_file_reader.read_event_object()) != nullptr) {
870
3/10
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 55 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
55 DBUG_PRINT("info", ("Read event of type %s", ev->get_type_str()));
871
4/6
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
55 switch (ev->get_type_code()) {
872 20 case binary_log::FORMAT_DESCRIPTION_EVENT:
873 case binary_log::START_5_7_ENCRYPTION_EVENT:
874 20 break;
875 8 case binary_log::ROTATE_EVENT:
876 /*
877 Check for rotate event from the master. Ignore the ROTATE event if it
878 is a fake rotate event with server_id=0.
879 */
880
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
8 if (ev->server_id && ev->server_id != ::server_id) {
881
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 Rotate_log_event *rotate_ev = (Rotate_log_event *)ev;
882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(FN_REFLEN >= rotate_ev->ident_len + 1);
883 4 memcpy(master_log_file, rotate_ev->new_log_ident,
884 4 rotate_ev->ident_len + 1);
885 4 *master_log_pos = rotate_ev->pos;
886 4 ret = FOUND_ROTATE;
887 4 done = true;
888 }
889 8 break;
890 20 case binary_log::PREVIOUS_GTIDS_LOG_EVENT:
891 20 break;
892 case binary_log::IGNORABLE_LOG_EVENT:
893 break;
894 7 case binary_log::STOP_EVENT:
895 7 break;
896 default:
897 LogErr(ERROR_LEVEL, ER_RPL_RECOVERY_NO_ROTATE_EVENT_FROM_MASTER);
898 ret = ERROR;
899 done = true;
900 break;
901 }
902
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 delete ev;
903 }
904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (relaylog_file_reader.has_fatal_error()) {
905 LogErr(ERROR_LEVEL, ER_RPL_RECOVERY_ERROR_READ_RELAY_LOG, -1);
906 return ERROR;
907 }
908 20 return ret;
909 20 }
910
911 /**
912 Reads relay logs one by one starting from the first relay log. Looks for
913 the first rotate event from the master. If rotate is not found in the relay
914 log search continues to next relay log. If rotate event from master is
915 found then the extracted master_log_file and master_log_pos are used to set
916 rli->group_master_log_name and rli->group_master_log_pos. If an error has
917 occurred the error code is returned back.
918
919 @param rli
920 Relay_log_info object to read relay log files and to set
921 group_master_log_name and group_master_log_pos.
922
923 @retval 0 Success - Rotate event was found
924 @retval 1 Failure - Found some events replicated but no rotate event was
925 found
926 @retval 2 When no rotate event from master was found. This can happen when
927 slave server was restarted immediately after executing CHANGE
928 MASTER
929 */
930 9 static int find_first_relay_log_with_rotate_from_master(Relay_log_info *rli) {
931
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 DBUG_TRACE;
932 9 int error = 0;
933 9 LOG_INFO linfo;
934 9 bool got_rotate_from_master = false;
935 int pos;
936 char master_log_file[FN_REFLEN];
937 9 my_off_t master_log_pos = 0;
938
939
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 if (channel_map.is_group_replication_channel_name(rli->get_channel())) {
940 LogErr(INFORMATION_LEVEL,
941 ER_RPL_RECOVERY_SKIPPED_GROUP_REPLICATION_CHANNEL);
942 goto err;
943 }
944
945
3/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 5 times.
25 for (pos = rli->relay_log.find_log_pos(&linfo, nullptr, true); !pos;
946
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 pos = rli->relay_log.find_next_log(&linfo, true)) {
947
3/6
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
20 switch (read_rotate_from_relay_log(linfo.log_file_name, master_log_file,
948 &master_log_pos)) {
949 case ERROR:
950 error = 1;
951 break;
952 4 case FOUND_ROTATE:
953 4 got_rotate_from_master = true;
954 4 break;
955 16 case NOT_FOUND_ROTATE:
956 16 break;
957 }
958
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 4 times.
20 if (error || got_rotate_from_master) break;
959 }
960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (pos == LOG_INFO_IO) {
961 error = 1;
962 LogErr(ERROR_LEVEL, ER_RPL_RECOVERY_IO_ERROR_READING_RELAY_LOG_INDEX);
963 goto err;
964 }
965
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (pos == LOG_INFO_EOF) {
966 5 error = 2;
967
8/16
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
5 LogErr(WARNING_LEVEL, ER_RPL_RECOVERY_NO_ROTATE_EVENT_FROM_MASTER);
968
8/16
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
5 LogErr(WARNING_LEVEL, ER_WARN_RPL_RECOVERY_NO_ROTATE_EVENT_FROM_MASTER_EOF,
969 rli->mi->get_channel());
970 5 goto err;
971 }
972
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (!error && got_rotate_from_master) {
973
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 rli->set_group_master_log_name(master_log_file);
974 4 rli->set_group_master_log_pos(master_log_pos);
975 }
976 err:
977 9 return error;
978 9 }
979
980 /*
981 Updates the master info based on the information stored in the
982 relay info and ignores relay logs previously retrieved by the IO
983 thread, which thus starts fetching again based on to the
984 master_log_pos and master_log_name. Eventually, the old
985 relay logs will be purged by the normal purge mechanism.
986
987 When GTID's are enabled the "Retrieved GTID" set should be cleared
988 so that partial read events are discarded and they are
989 fetched once again
990
991 @param mi pointer to Master_info instance
992 */
993 224 static void recover_relay_log(Master_info *mi) {
994 224 Relay_log_info *rli = mi->rli;
995
996 // If GTID ONLY is enable the receiver doesn't care about these positions
997
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 5 times.
224 if (!mi->is_gtid_only_mode()) {
998 // Set Receiver Thread's positions as per the recovered Applier Thread.
999 219 mi->set_master_log_pos(std::max<ulonglong>(
1000 219 BIN_LOG_HEADER_SIZE, rli->get_group_master_log_pos()));
1001 219 mi->set_master_log_name(rli->get_group_master_log_name());
1002
1003
8/16
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 219 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 219 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 219 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 219 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 219 times.
✗ Branch 15 not taken.
219 LogErr(WARNING_LEVEL, ER_RPL_RECOVERY_FILE_MASTER_POS_INFO,
1004 (ulong)mi->get_master_log_pos(), mi->get_master_log_name(),
1005 mi->get_for_channel_str(), rli->get_group_relay_log_pos(),
1006 rli->get_group_relay_log_name());
1007 } else {
1008
7/14
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
5 LogErr(WARNING_LEVEL, ER_RPL_RELAY_LOG_RECOVERY_GTID_ONLY);
1009 }
1010
1011 // Start with a fresh relay log.
1012 224 rli->set_group_relay_log_name(rli->relay_log.get_log_fname());
1013 224 rli->set_group_relay_log_pos(BIN_LOG_HEADER_SIZE);
1014 /*
1015 Clear the retrieved GTID set so that events that are written partially
1016 will be fetched again.
1017 */
1018
4/4
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 169 times.
✓ Branch 2 taken 53 times.
✓ Branch 3 taken 171 times.
279 if (global_gtid_mode.get() == Gtid_mode::ON &&
1019
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 2 times.
55 !channel_map.is_group_replication_channel_name(rli->get_channel())) {
1020 53 rli->get_sid_lock()->wrlock();
1021 53 (const_cast<Gtid_set *>(rli->get_gtid_set()))->clear_set_and_sid_map();
1022 53 rli->get_sid_lock()->unlock();
1023 }
1024 224 }
1025
1026 /*
1027 Updates the master info based on the information stored in the
1028 relay info and ignores relay logs previously retrieved by the IO
1029 thread, which thus starts fetching again based on to the
1030 master_log_pos and master_log_name. Eventually, the old
1031 relay logs will be purged by the normal purge mechanism.
1032
1033 There can be a special case where rli->group_master_log_name and
1034 rli->group_master_log_pos are not initialized, as the sql thread was never
1035 started at all. In those cases all the existing relay logs are parsed
1036 starting from the first one and the initial rotate event that was received
1037 from the master is identified. From the rotate event master_log_name and
1038 master_log_pos are extracted and they are set to rli->group_master_log_name
1039 and rli->group_master_log_pos.
1040
1041 In the feature, we should improve this routine in order to avoid throwing
1042 away logs that are safely stored in the disk. Note also that this recovery
1043 routine relies on the correctness of the relay-log.info and only tolerates
1044 coordinate problems in master.info.
1045
1046 In this function, there is no need for a mutex as the caller
1047 (i.e. init_replica) already has one acquired.
1048
1049 Specifically, the following structures are updated:
1050
1051 1 - mi->master_log_pos <-- rli->group_master_log_pos
1052 2 - mi->master_log_name <-- rli->group_master_log_name
1053 3 - It moves the relay log to the new relay log file, by
1054 rli->group_relay_log_pos <-- BIN_LOG_HEADER_SIZE;
1055 rli->event_relay_log_pos <-- BIN_LOG_HEADER_SIZE;
1056 rli->group_relay_log_name <-- rli->relay_log.get_log_fname();
1057 rli->event_relay_log_name <-- rli->relay_log.get_log_fname();
1058
1059 If there is an error, it returns (1), otherwise returns (0).
1060 */
1061 233 int init_recovery(Master_info *mi) {
1062
1/2
✓ Branch 0 taken 233 times.
✗ Branch 1 not taken.
233 DBUG_TRACE;
1063
1064 233 int error = 0;
1065 233 Relay_log_info *rli = mi->rli;
1066 233 char *group_master_log_name = nullptr;
1067
1068 /*
1069 This is not idempotent and a crash after this function and before
1070 the recovery is actually done may lead the system to an inconsistent
1071 state.
1072
1073 This may happen because the gap is not persitent stored anywhere
1074 and eventually old relay log files will be removed and further
1075 calculations on the gaps will be impossible.
1076
1077 We need to improve this. /Alfranio.
1078 */
1079
1/2
✓ Branch 0 taken 233 times.
✗ Branch 1 not taken.
233 error = mts_recovery_groups(rli);
1080
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 162 times.
233 if (rli->mts_recovery_group_cnt) return error;
1081
1082 162 group_master_log_name = const_cast<char *>(rli->get_group_master_log_name());
1083
1/2
✓ Branch 0 taken 162 times.
✗ Branch 1 not taken.
162 if (!error) {
1084 162 bool run_relay_log_recovery = true;
1085
7/8
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 150 times.
162 if (!group_master_log_name[0] && !rli->mi->is_gtid_only_mode()) {
1086
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (rli->replicate_same_server_id) {
1087 3 error = 1;
1088
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(ERROR_LEVEL,
1089 ER_RPL_RECOVERY_REPLICATE_SAME_SERVER_ID_REQUIRES_POSITION);
1090 3 return error;
1091 }
1092
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 error = find_first_relay_log_with_rotate_from_master(rli);
1093
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (error == 2) {
1094 // No events from the master on relay log - skip relay log recovery
1095 5 run_relay_log_recovery = false;
1096 5 error = 0;
1097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 } else if (error)
1098 return error;
1099 }
1100
3/4
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
159 if (run_relay_log_recovery) recover_relay_log(mi);
1101 }
1102 159 return error;
1103 233 }
1104
1105 /*
1106 Relay log recovery in the case of MTS, is handled by the following function.
1107 Gaps in MTS execution are filled using implicit execution of
1108 START SLAVE UNTIL SQL_AFTER_MTS_GAPS call. Once slave reaches a consistent
1109 gapless state receiver thread's positions are initialized to applier thread's
1110 positions and the old relay logs are discarded. This completes the recovery
1111 process.
1112
1113 @param mi pointer to Master_info instance.
1114
1115 @retval 0 success
1116 @retval 1 error
1117 */
1118 71 static inline int fill_mts_gaps_and_recover(Master_info *mi) {
1119
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 DBUG_TRACE;
1120 71 Relay_log_info *rli = mi->rli;
1121 71 int recovery_error = 0;
1122 71 rli->is_relay_log_recovery = false;
1123
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 Until_mts_gap *until_mg = new Until_mts_gap(rli);
1124
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 rli->set_until_option(until_mg);
1125 71 rli->until_condition = Relay_log_info::UNTIL_SQL_AFTER_MTS_GAPS;
1126
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 until_mg->init();
1127 71 rli->channel_mts_submode = (mts_parallel_option == MTS_PARALLEL_TYPE_DB_NAME)
1128 71 ? MTS_PARALLEL_TYPE_DB_NAME
1129 : MTS_PARALLEL_TYPE_LOGICAL_CLOCK;
1130
8/16
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 71 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 71 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 71 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 71 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 71 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 71 times.
✗ Branch 15 not taken.
71 LogErr(INFORMATION_LEVEL, ER_RPL_MTS_RECOVERY_STARTING_COORDINATOR);
1131
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 recovery_error = start_slave_thread(
1132 key_thread_replica_sql, handle_slave_sql, &rli->run_lock, &rli->run_lock,
1133 &rli->start_cond, &rli->slave_running, &rli->slave_run_id, mi);
1134
1135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
71 if (recovery_error) {
1136 LogErr(WARNING_LEVEL, ER_RPL_MTS_RECOVERY_FAILED_TO_START_COORDINATOR);
1137 goto err;
1138 }
1139
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 mysql_mutex_lock(&rli->run_lock);
1140
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 mysql_cond_wait(&rli->stop_cond, &rli->run_lock);
1141
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 mysql_mutex_unlock(&rli->run_lock);
1142
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 70 times.
71 if (rli->until_condition != Relay_log_info::UNTIL_DONE) {
1143
8/16
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
1 LogErr(WARNING_LEVEL, ER_RPL_MTS_AUTOMATIC_RECOVERY_FAILED);
1144 1 goto err;
1145 }
1146
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 rli->clear_until_option();
1147 /*
1148 We need a mutex while we are changing master info parameters to
1149 keep other threads from reading bogus info
1150 */
1151
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 mysql_mutex_lock(&mi->data_lock);
1152
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 mysql_mutex_lock(&rli->data_lock);
1153
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 recover_relay_log(mi);
1154
1155
3/6
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 70 times.
140 if (mi->flush_info(true) ||
1156
2/4
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
70 rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT)) {
1157 recovery_error = 1;
1158 mysql_mutex_unlock(&mi->data_lock);
1159 mysql_mutex_unlock(&rli->data_lock);
1160 goto err;
1161 }
1162 70 rli->inited = true;
1163 70 rli->error_on_rli_init_info = false;
1164
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 mysql_mutex_unlock(&mi->data_lock);
1165
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 mysql_mutex_unlock(&rli->data_lock);
1166
8/16
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 70 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 70 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 70 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 70 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 70 times.
✗ Branch 15 not taken.
70 LogErr(INFORMATION_LEVEL, ER_RPL_MTS_RECOVERY_SUCCESSFUL);
1167 70 return recovery_error;
1168 1 err:
1169 /*
1170 If recovery failed means we failed to initialize rli object in the case
1171 of MTS. We should not allow the START SLAVE command to work as we do in
1172 the case of STS. i.e if init_recovery call fails then we set inited=0.
1173 */
1174
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->end_info();
1175 1 rli->inited = false;
1176 1 rli->error_on_rli_init_info = true;
1177
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->clear_until_option();
1178 1 return recovery_error;
1179 71 }
1180
1181 25277 int load_mi_and_rli_from_repositories(Master_info *mi, bool ignore_if_no_info,
1182 int thread_mask,
1183 bool skip_received_gtid_set_recovery,
1184 bool force_load) {
1185
1/2
✓ Branch 0 taken 25277 times.
✗ Branch 1 not taken.
25277 DBUG_TRACE;
1186
2/4
✓ Branch 0 taken 25277 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25277 times.
✗ Branch 3 not taken.
25277 assert(mi != nullptr && mi->rli != nullptr);
1187 25277 int init_error = 0;
1188 25277 enum_return_check check_return = ERROR_CHECKING_REPOSITORY;
1189
1/2
✓ Branch 0 taken 25277 times.
✗ Branch 1 not taken.
25277 THD *thd = current_thd;
1190
1191 /*
1192 We need a mutex while we are changing master info parameters to
1193 keep other threads from reading bogus info
1194 */
1195
1/2
✓ Branch 0 taken 25277 times.
✗ Branch 1 not taken.
25277 mysql_mutex_lock(&mi->data_lock);
1196
1/2
✓ Branch 0 taken 25277 times.
✗ Branch 1 not taken.
25277 mysql_mutex_lock(&mi->rli->data_lock);
1197
1198 /*
1199 When info tables are used and autocommit= 0 we force a new
1200 transaction start to avoid table access deadlocks when START SLAVE
1201 is executed after RESET SLAVE.
1202 */
1203
3/4
✓ Branch 0 taken 25277 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 25272 times.
25277 if (is_autocommit_off_and_infotables(thd)) {
1204
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (trans_begin(thd)) {
1205 init_error = 1;
1206 goto end;
1207 }
1208 }
1209
1210 /*
1211 This takes care of the startup dependency between the master_info
1212 and relay_info. It initializes the master info if the SLAVE_IO
1213 thread is being started and the relay log info if either the
1214 SLAVE_SQL thread is being started or was not initialized as it is
1215 required by the SLAVE_IO thread.
1216 */
1217
1/2
✓ Branch 0 taken 25271 times.
✗ Branch 1 not taken.
25277 check_return = mi->check_info();
1218
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 25269 times.
25271 if (check_return == ERROR_CHECKING_REPOSITORY) {
1219 2 init_error = 1;
1220 2 goto end;
1221 }
1222
1223
3/4
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 24557 times.
✓ Branch 2 taken 712 times.
✗ Branch 3 not taken.
25269 if (!ignore_if_no_info || check_return != REPOSITORY_DOES_NOT_EXIST) {
1224
2/2
✓ Branch 0 taken 21472 times.
✓ Branch 1 taken 3797 times.
25269 if ((thread_mask & SLAVE_IO) != 0) {
1225
3/4
✓ Branch 0 taken 9353 times.
✓ Branch 1 taken 12119 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9353 times.
21472 if (!mi->inited || force_load) {
1226
3/4
✓ Branch 0 taken 12119 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 12115 times.
12119 if (mi->mi_init_info()) {
1227 4 init_error = 1;
1228 }
1229 }
1230 }
1231 }
1232
1233
1/2
✓ Branch 0 taken 25269 times.
✗ Branch 1 not taken.
25269 check_return = mi->rli->check_info();
1234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25269 times.
25269 if (check_return == ERROR_CHECKING_REPOSITORY) {
1235 init_error = 1;
1236 goto end;
1237 }
1238
4/4
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 24557 times.
✓ Branch 2 taken 709 times.
✓ Branch 3 taken 3 times.
25269 if (!ignore_if_no_info || check_return != REPOSITORY_DOES_NOT_EXIST) {
1239
4/4
✓ Branch 0 taken 766 times.
✓ Branch 1 taken 24500 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 738 times.
25266 if ((thread_mask & SLAVE_SQL) != 0 || !(mi->rli->inited)) {
1240
4/4
✓ Branch 0 taken 12403 times.
✓ Branch 1 taken 12125 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 12385 times.
24528 if (!mi->rli->inited || force_load) {
1241
3/4
✓ Branch 0 taken 12143 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 12135 times.
12143 if (mi->rli->rli_init_info(skip_received_gtid_set_recovery)) {
1242 8 init_error = 1;
1243 } else {
1244 /*
1245 During rli_init_info() above, the relay log is opened (if rli was
1246 not initialized yet). The function below expects the relay log to be
1247 opened to get its coordinates and store as the last flushed relay
1248 log coordinates from I/O thread point of view.
1249 */
1250
1/2
✓ Branch 0 taken 12135 times.
✗ Branch 1 not taken.
12135 mi->update_flushed_relay_log_info();
1251 }
1252 } else {
1253 // Even if we skip rli_init_info we must check if gaps exist to maintain
1254 // the server behavior in commands like CHANGE REPLICATION SOURCE
1255
5/6
✓ Branch 0 taken 4167 times.
✓ Branch 1 taken 8218 times.
✓ Branch 2 taken 4167 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 12384 times.
12385 if (mi->rli->recovery_parallel_workers ? mts_recovery_groups(mi->rli)
1256 : 0)
1257 1 init_error = 1;
1258 }
1259 }
1260 }
1261
1262
2/6
✓ Branch 0 taken 25269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25269 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
25269 DBUG_EXECUTE_IF("enable_mta_worker_failure_init",
1263 { DBUG_SET("+d,mta_worker_thread_init_fails"); });
1264 25269 end:
1265 /*
1266 When info tables are used and autocommit= 0 we force transaction
1267 commit to avoid table access deadlocks when START SLAVE is executed
1268 after RESET SLAVE.
1269 */
1270
3/4
✓ Branch 0 taken 25271 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 25266 times.
25271 if (is_autocommit_off_and_infotables(thd))
1271
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (trans_commit(thd)) init_error = 1;
1272
1273
1/2
✓ Branch 0 taken 25271 times.
✗ Branch 1 not taken.
25271 mysql_mutex_unlock(&mi->rli->data_lock);
1274
1/2
✓ Branch 0 taken 25271 times.
✗ Branch 1 not taken.
25271 mysql_mutex_unlock(&mi->data_lock);
1275
1276 /*
1277 Handling MTS Relay-log recovery after successful initialization of mi and
1278 rli objects.
1279
1280 MTS Relay-log recovery is handled by SSUG command. In order to start the
1281 slave applier thread rli needs to be inited and mi->rli->data_lock should
1282 be in released state. Hence we do the MTS recovery at this point of time
1283 where both conditions are satisfied.
1284 */
1285
4/4
✓ Branch 0 taken 25256 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 25185 times.
25271 if (!init_error && mi->rli->is_relay_log_recovery &&
1286
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 mi->rli->mts_recovery_group_cnt)
1287
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 init_error = fill_mts_gaps_and_recover(mi);
1288 25271 return init_error;
1289 25271 }
1290
1291 24357 void end_info(Master_info *mi) {
1292
1/2
✓ Branch 0 taken 24357 times.
✗ Branch 1 not taken.
24357 DBUG_TRACE;
1293
2/4
✓ Branch 0 taken 24357 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24357 times.
✗ Branch 3 not taken.
24357 assert(mi != nullptr && mi->rli != nullptr);
1294
1295 /*
1296 The previous implementation was not acquiring locks. We do the same here.
1297 However, this is quite strange.
1298 */
1299
1/2
✓ Branch 0 taken 24357 times.
✗ Branch 1 not taken.
24357 mi->end_info();
1300
1/2
✓ Branch 0 taken 24357 times.
✗ Branch 1 not taken.
24357 mi->rli->end_info();
1301 24357 }
1302
1303 12983 void clear_info(Master_info *mi) {
1304
1/2
✓ Branch 0 taken 12983 times.
✗ Branch 1 not taken.
12983 DBUG_TRACE;
1305
2/4
✓ Branch 0 taken 12983 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12983 times.
✗ Branch 3 not taken.
12983 assert(mi != nullptr && mi->rli != nullptr);
1306
1307 /*
1308 Reset errors (the idea is that we forget about the
1309 old master).
1310 */
1311
1/2
✓ Branch 0 taken 12983 times.
✗ Branch 1 not taken.
12983 mi->clear_error();
1312
1/2
✓ Branch 0 taken 12983 times.
✗ Branch 1 not taken.
12983 mi->rli->clear_error();
1313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12983 times.
12983 if (mi->rli->workers_array_initialized) {
1314 for (size_t i = 0; i < mi->rli->get_worker_count(); i++) {
1315 mi->rli->get_worker(i)->clear_error();
1316 }
1317 }
1318 12983 mi->rli->clear_sql_delay();
1319
1320
1/2
✓ Branch 0 taken 12983 times.
✗ Branch 1 not taken.
12983 end_info(mi);
1321 12983 }
1322
1323 9201 int remove_info(Master_info *mi) {
1324 9201 int error = 1;
1325
1/2
✓ Branch 0 taken 9201 times.
✗ Branch 1 not taken.
9201 DBUG_TRACE;
1326
2/4
✓ Branch 0 taken 9201 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9201 times.
✗ Branch 3 not taken.
9201 assert(mi != nullptr && mi->rli != nullptr);
1327
1328 /*
1329 The previous implementation was not acquiring locks.
1330 We do the same here. However, this is quite strange.
1331 */
1332
1/2
✓ Branch 0 taken 9201 times.
✗ Branch 1 not taken.
9201 clear_info(mi);
1333
1334
7/10
✓ Branch 0 taken 9201 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9201 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9201 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9200 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 9200 times.
18401 if (mi->remove_info() || Rpl_info_factory::reset_workers(mi->rli) ||
1335
2/4
✓ Branch 0 taken 9200 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9200 times.
9200 mi->rli->remove_info())
1336 1 goto err;
1337
1338 9200 error = 0;
1339
1340 9201 err:
1341 9201 return error;
1342 9201 }
1343
1344 3782 bool reset_info(Master_info *mi) {
1345
1/2
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
3782 DBUG_TRACE;
1346
2/4
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3782 times.
✗ Branch 3 not taken.
3782 assert(mi != nullptr && mi->rli != nullptr);
1347
1348
1/2
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
3782 clear_info(mi);
1349
1350
5/10
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3782 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3782 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3782 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3782 times.
3782 if (mi->remove_info() || Rpl_info_factory::reset_workers(mi->rli))
1351 return true;
1352
1353 3782 MUTEX_LOCK(mi_lock, &mi->data_lock);
1354 3782 MUTEX_LOCK(rli_lock, &mi->rli->data_lock);
1355
1356
1/2
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
3782 mi->init_master_log_pos();
1357 3782 mi->master_uuid[0] = 0;
1358
1359
2/2
✓ Branch 0 taken 3744 times.
✓ Branch 1 taken 14 times.
3758 if (mi->reset && opt_mi_repository_id == INFO_REPOSITORY_TABLE &&
1360
7/10
✓ Branch 0 taken 3758 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 3741 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3741 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3741 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3782 times.
7540 opt_rli_repository_id == INFO_REPOSITORY_TABLE && mi->flush_info(true)) {
1361 my_error(ER_MASTER_INFO, MYF(0));
1362 return true;
1363 }
1364
1365 bool have_relay_log_data_to_persist = // Only want to keep
1366
1/2
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
3782 (!mi->rli->is_privilege_checks_user_null() || // if PCU is not null
1367
3/4
✓ Branch 0 taken 3766 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1136 times.
✓ Branch 3 taken 2630 times.
3766 mi->rli->is_row_format_required() || // or RRF is 1
1368 Relay_log_info::PK_CHECK_STREAM != // or RTPKC != STREAM
1369
2/4
✓ Branch 0 taken 1136 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1136 times.
1136 mi->rli->get_require_table_primary_key_check()) &&
1370
3/4
✓ Branch 0 taken 3766 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 2646 times.
✗ Branch 3 not taken.
10194 opt_rli_repository_id == INFO_REPOSITORY_TABLE && // in TABLE repository.
1371
1/2
✓ Branch 0 taken 2646 times.
✗ Branch 1 not taken.
2646 opt_mi_repository_id == INFO_REPOSITORY_TABLE;
1372
1373
5/8
✓ Branch 0 taken 2646 times.
✓ Branch 1 taken 1136 times.
✓ Branch 2 taken 2646 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2646 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3782 times.
7564 if ((have_relay_log_data_to_persist && mi->rli->clear_info()) ||
1374
4/6
✓ Branch 0 taken 1136 times.
✓ Branch 1 taken 2646 times.
✓ Branch 2 taken 1136 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1136 times.
3782 (!have_relay_log_data_to_persist && mi->rli->remove_info())) {
1375 my_error(ER_MASTER_INFO, MYF(0));
1376 return true;
1377 }
1378
1379 3782 return false;
1380 3782 }
1381
1382 1568310 int flush_master_info(Master_info *mi, bool force, bool need_lock,
1383 bool do_flush_relay_log, bool skip_repo_persistence) {
1384
1/2
✓ Branch 0 taken 1568310 times.
✗ Branch 1 not taken.
1568310 DBUG_TRACE;
1385
2/4
✓ Branch 0 taken 1568310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1568310 times.
✗ Branch 3 not taken.
1568310 assert(mi != nullptr && mi->rli != nullptr);
1386
3/4
✓ Branch 0 taken 1568310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1568309 times.
1568310 DBUG_EXECUTE_IF("fail_to_flush_source_info", { return 1; });
1387
1388
3/4
✓ Branch 0 taken 59552 times.
✓ Branch 1 taken 1508757 times.
✓ Branch 2 taken 59552 times.
✗ Branch 3 not taken.
1568309 if (skip_repo_persistence && !do_flush_relay_log) {
1389 59552 return 0;
1390 }
1391
1392 /*
1393 With the appropriate recovery process, we will not need to flush
1394 the content of the current log.
1395
1396 For now, we flush the relay log BEFORE the master.info file, because
1397 if we crash, we will get a duplicate event in the relay log at restart.
1398 If we change the order, there might be missing events.
1399
1400 If we don't do this and the slave server dies when the relay log has
1401 some parts (its last kilobytes) in memory only, with, say, from master's
1402 position 100 to 150 in memory only (not on disk), and with position 150
1403 in master.info, there will be missing information. When the slave restarts,
1404 the I/O thread will fetch binlogs from 150, so in the relay log we will
1405 have "[0, 100] U [150, infinity[" and nobody will notice it, so the SQL
1406 thread will jump from 100 to 150, and replication will silently break.
1407 */
1408 1508757 mysql_mutex_t *log_lock = mi->rli->relay_log.get_log_lock();
1409 1508757 mysql_mutex_t *data_lock = &mi->data_lock;
1410
1411
2/2
✓ Branch 0 taken 12631 times.
✓ Branch 1 taken 1496126 times.
1508757 if (need_lock) {
1412
1/2
✓ Branch 0 taken 12631 times.
✗ Branch 1 not taken.
12631 mysql_mutex_lock(log_lock);
1413
1/2
✓ Branch 0 taken 12631 times.
✗ Branch 1 not taken.
12631 mysql_mutex_lock(data_lock);
1414 } else {
1415 1496126 mysql_mutex_assert_owner(log_lock);
1416 1496126 mysql_mutex_assert_owner(&mi->data_lock);
1417 }
1418
1419 1508757 int err = 0;
1420 /*
1421 We can skip flushing the relay log when this function is called from
1422 queue_event(), as after_write_to_relay_log() will already flush it.
1423 */
1424
3/4
✓ Branch 0 taken 12601 times.
✓ Branch 1 taken 1496156 times.
✓ Branch 2 taken 12601 times.
✗ Branch 3 not taken.
1508757 if (do_flush_relay_log) err |= mi->rli->flush_current_log();
1425
1426
2/4
✓ Branch 0 taken 1508757 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1508756 times.
✗ Branch 3 not taken.
1508757 if (!skip_repo_persistence) err |= mi->flush_info(force);
1427
1428
2/2
✓ Branch 0 taken 12631 times.
✓ Branch 1 taken 1496125 times.
1508756 if (need_lock) {
1429
1/2
✓ Branch 0 taken 12631 times.
✗ Branch 1 not taken.
12631 mysql_mutex_unlock(data_lock);
1430
1/2
✓ Branch 0 taken 12631 times.
✗ Branch 1 not taken.
12631 mysql_mutex_unlock(log_lock);
1431 }
1432
1433 1508756 return err;
1434 1568309 }
1435
1436 /**
1437 Convert slave skip errors bitmap into a printable string.
1438 */
1439
1440 11405 static void print_replica_skip_errors(void) {
1441 /*
1442 To be safe, we want 10 characters of room in the buffer for a number
1443 plus terminators. Also, we need some space for constant strings.
1444 10 characters must be sufficient for a number plus {',' | '...'}
1445 plus a NUL terminator. That is a max 6 digit number.
1446 */
1447 11405 const size_t MIN_ROOM = 10;
1448
1/2
✓ Branch 0 taken 11405 times.
✗ Branch 1 not taken.
11405 DBUG_TRACE;
1449 assert(sizeof(slave_skip_error_names) > MIN_ROOM);
1450 assert(MAX_SLAVE_ERROR <= 999999); // 6 digits
1451
1452
7/8
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 11373 times.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 31 times.
✓ Branch 6 taken 11374 times.
✓ Branch 7 taken 31 times.
11405 if (!use_slave_mask || bitmap_is_clear_all(&slave_error_mask)) {
1453 /* purecov: begin tested */
1454 11374 memcpy(slave_skip_error_names, STRING_WITH_LEN("OFF"));
1455 /* purecov: end */
1456
3/4
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 29 times.
31 } else if (bitmap_is_set_all(&slave_error_mask)) {
1457 /* purecov: begin tested */
1458 2 memcpy(slave_skip_error_names, STRING_WITH_LEN("ALL"));
1459 /* purecov: end */
1460 } else {
1461 29 char *buff = slave_skip_error_names;
1462 29 char *bend = buff + sizeof(slave_skip_error_names);
1463 int errnum;
1464
1465
2/2
✓ Branch 0 taken 406000 times.
✓ Branch 1 taken 29 times.
406029 for (errnum = 0; errnum < MAX_SLAVE_ERROR; errnum++) {
1466
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 405928 times.
406000 if (bitmap_is_set(&slave_error_mask, errnum)) {
1467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (buff + MIN_ROOM >= bend) break; /* purecov: tested */
1468
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 buff = longlong10_to_str(errnum, buff, -10);
1469 72 *buff++ = ',';
1470 }
1471 }
1472
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (buff != slave_skip_error_names) buff--; // Remove last ','
1473 /*
1474 The range for client side error is [2000-2999]
1475 so if the errnum doesn't lie in that and if less
1476 than MAX_SLAVE_ERROR[10000] we enter the if loop.
1477 */
1478
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
29 if (errnum < MAX_SLAVE_ERROR &&
1479 (errnum < CR_MIN_ERROR || errnum > CR_MAX_ERROR)) {
1480 /* Couldn't show all errors */
1481 buff = my_stpcpy(buff, "..."); /* purecov: tested */
1482 }
1483 29 *buff = 0;
1484 }
1485
3/8
✓ Branch 0 taken 11405 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11405 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11405 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
11405 DBUG_PRINT("init", ("error_names: '%s'", slave_skip_error_names));
1486 11405 }
1487
1488 /**
1489 Change arg to the string with the nice, human-readable skip error values.
1490 @param replica_skip_errors_ptr
1491 The pointer to be changed
1492 */
1493 11405 void set_replica_skip_errors(char **replica_skip_errors_ptr) {
1494
1/2
✓ Branch 0 taken 11405 times.
✗ Branch 1 not taken.
11405 DBUG_TRACE;
1495
1/2
✓ Branch 0 taken 11405 times.
✗ Branch 1 not taken.
11405 print_replica_skip_errors();
1496 11405 *replica_skip_errors_ptr = slave_skip_error_names;
1497 11405 }
1498
1499 /**
1500 Init function to set up array for errors that should be skipped for slave
1501 */
1502 32 static void init_replica_skip_errors() {
1503
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 DBUG_TRACE;
1504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 assert(!use_slave_mask); // not already initialized
1505
1506
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
32 if (bitmap_init(&slave_error_mask, nullptr, MAX_SLAVE_ERROR)) {
1507 fprintf(stderr, "Badly out of memory, please check your system status\n");
1508 exit(MYSQLD_ABORT_EXIT);
1509 }
1510 32 use_slave_mask = true;
1511 32 }
1512
1513 1 static void add_replica_skip_errors(const uint *errors, uint n_errors) {
1514
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 DBUG_TRACE;
1515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(errors);
1516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(use_slave_mask);
1517
1518
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 for (uint i = 0; i < n_errors; i++) {
1519 10 const uint err_code = errors[i];
1520 /*
1521 The range for client side error is [2000-2999]
1522 so if the err_code doesn't lie in that and if less
1523 than MAX_SLAVE_ERROR[14000] we enter the if loop.
1524 */
1525
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (err_code < MAX_SLAVE_ERROR &&
1526 (err_code < CR_MIN_ERROR || err_code > CR_MAX_ERROR))
1527 10 bitmap_set_bit(&slave_error_mask, err_code);
1528 }
1529 1 }
1530
1531 /*
1532 Add errors that should be skipped for slave
1533
1534 SYNOPSIS
1535 add_replica_skip_errors()
1536 arg List of errors numbers to be added to skip, separated with ','
1537
1538 NOTES
1539 Called from get_options() in mysqld.cc on start-up
1540 */
1541
1542 32 void add_replica_skip_errors(const char *arg) {
1543 32 const char *p = nullptr;
1544 /*
1545 ALL is only valid when nothing else is provided.
1546 */
1547 32 const uchar SKIP_ALL[] = "all";
1548 32 size_t SIZE_SKIP_ALL = strlen((const char *)SKIP_ALL) + 1;
1549 /*
1550 IGNORE_DDL_ERRORS can be combined with other parameters
1551 but must be the first one provided.
1552 */
1553 32 const uchar SKIP_DDL_ERRORS[] = "ddl_exist_errors";
1554 32 size_t SIZE_SKIP_DDL_ERRORS = strlen((const char *)SKIP_DDL_ERRORS);
1555
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 DBUG_TRACE;
1556
1557 // initialize mask if not done yet
1558
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
32 if (!use_slave_mask) init_replica_skip_errors();
1559
1560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 for (; my_isspace(system_charset_info, *arg); ++arg) /* empty */
1561 ;
1562
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 30 times.
32 if (!my_strnncoll(system_charset_info, pointer_cast<const uchar *>(arg),
1563 SIZE_SKIP_ALL, SKIP_ALL, SIZE_SKIP_ALL)) {
1564 2 bitmap_set_all(&slave_error_mask);
1565 2 return;
1566 }
1567
3/4
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 29 times.
30 if (!my_strnncoll(system_charset_info, pointer_cast<const uchar *>(arg),
1568 SIZE_SKIP_DDL_ERRORS, SKIP_DDL_ERRORS,
1569 SIZE_SKIP_DDL_ERRORS)) {
1570 // DDL errors to be skipped for relaxed 'exist' handling
1571 1 const uint ddl_errors[] = {
1572 // error codes with create/add <schema object>
1573 ER_DB_CREATE_EXISTS, ER_TABLE_EXISTS_ERROR, ER_DUP_KEYNAME,
1574 ER_MULTIPLE_PRI_KEY,
1575 // error codes with change/rename <schema object>
1576 ER_BAD_FIELD_ERROR, ER_NO_SUCH_TABLE, ER_DUP_FIELDNAME,
1577 // error codes with drop <schema object>
1578 ER_DB_DROP_EXISTS, ER_BAD_TABLE_ERROR, ER_CANT_DROP_FIELD_OR_KEY};
1579
1580
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 add_replica_skip_errors(ddl_errors,
1581 sizeof(ddl_errors) / sizeof(ddl_errors[0]));
1582 /*
1583 After processing the SKIP_DDL_ERRORS, the pointer is
1584 increased to the position after the comma.
1585 */
1586
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (strlen(arg) > SIZE_SKIP_DDL_ERRORS + 1) arg += SIZE_SKIP_DDL_ERRORS + 1;
1587 }
1588
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 29 times.
92 for (p = arg; *p;) {
1589 long err_code;
1590
3/4
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 62 times.
63 if (!(p = str2int(p, 10, 0, LONG_MAX, &err_code))) break;
1591
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 if (err_code < MAX_SLAVE_ERROR)
1592 62 bitmap_set_bit(&slave_error_mask, (uint)err_code);
1593
4/4
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 29 times.
95 while (!my_isdigit(system_charset_info, *p) && *p) p++;
1594 }
1595
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 2 times.
32 }
1596
1597 20525 static void set_thd_in_use_temporary_tables(Relay_log_info *rli) {
1598 TABLE *table;
1599
1600
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 20525 times.
20560 for (table = rli->save_temporary_tables; table; table = table->next) {
1601 35 table->in_use = rli->info_thd;
1602
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if (table->file != nullptr) {
1603 /*
1604 Since we are stealing opened temporary tables from one thread to
1605 another, we need to let the performance schema know that, for aggregates
1606 per thread to work properly.
1607 */
1608 35 table->file->unbind_psi();
1609 35 table->file->rebind_psi();
1610 }
1611 }
1612 20525 }
1613
1614 19422 int terminate_slave_threads(Master_info *mi, int thread_mask,
1615 ulong stop_wait_timeout, bool need_lock_term) {
1616
1/2
✓ Branch 0 taken 19422 times.
✗ Branch 1 not taken.
19422 DBUG_TRACE;
1617
1618
2/2
✓ Branch 0 taken 7905 times.
✓ Branch 1 taken 11517 times.
19422 if (!mi->inited) return 0; /* successfully do nothing */
1619 11517 int error, force_all = (thread_mask & SLAVE_FORCE_ALL);
1620 11517 mysql_mutex_t *sql_lock{&mi->rli->run_lock}, *io_lock{&mi->run_lock};
1621 11517 mysql_mutex_t *log_lock = mi->rli->relay_log.get_log_lock();
1622 /*
1623 Set it to a variable, so the value is shared by both stop methods.
1624 This guarantees that the user defined value for the timeout value is for
1625 the time the 2 threads take to shutdown, and not the time of each thread
1626 stop operation.
1627 */
1628 11517 ulong total_stop_wait_timeout = stop_wait_timeout;
1629
1630
2/2
✓ Branch 0 taken 10719 times.
✓ Branch 1 taken 798 times.
11517 if (thread_mask & (SLAVE_SQL | SLAVE_FORCE_ALL)) {
1631
3/8
✓ Branch 0 taken 10719 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10719 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10719 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10719 DBUG_PRINT("info", ("Terminating SQL thread"));
1632 10719 mi->rli->abort_slave = true;
1633 32157 if ((error = terminate_slave_thread(
1634 10719 mi->rli->info_thd, sql_lock, &mi->rli->stop_cond,
1635
1/2
✓ Branch 0 taken 10719 times.
✗ Branch 1 not taken.
10719 &mi->rli->slave_running, &total_stop_wait_timeout,
1636
5/6
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 10711 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 10711 times.
10719 need_lock_term)) &&
1637 !force_all) {
1638
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (error == 1) {
1639 8 return ER_STOP_SLAVE_SQL_THREAD_TIMEOUT;
1640 }
1641 return error;
1642 }
1643
1644
3/8
✓ Branch 0 taken 10711 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10711 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10711 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10711 DBUG_PRINT("info", ("Flushing relay-log info file."));
1645
3/4
✓ Branch 0 taken 10711 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8759 times.
✓ Branch 3 taken 1952 times.
10711 if (current_thd)
1646
2/4
✓ Branch 0 taken 8759 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8759 times.
✗ Branch 3 not taken.
8759 THD_STAGE_INFO(current_thd, stage_flushing_relay_log_info_file);
1647
1648 /*
1649 Flushes the relay log info regardless of the sync_relay_log_info option.
1650 */
1651
2/4
✓ Branch 0 taken 10711 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10711 times.
10711 if (mi->rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT)) {
1652 return ER_ERROR_DURING_FLUSH_LOGS;
1653 }
1654 }
1655
1656 /*
1657 Only stops the monitoring thread if this is the only failover channel
1658 running.
1659 */
1660
4/4
✓ Branch 0 taken 2021 times.
✓ Branch 1 taken 9488 times.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 11441 times.
13530 if ((thread_mask & (SLAVE_MONITOR | SLAVE_FORCE_ALL)) &&
1661
3/4
✓ Branch 0 taken 2021 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 1953 times.
2021 channel_map.get_number_of_connection_auto_failover_channels_running() ==
1662 1) {
1663
3/8
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 68 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
68 DBUG_PRINT("info", ("Terminating Monitor IO thread"));
1664 68 if ((error = Source_IO_monitor::get_instance()
1665
4/10
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 68 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 68 times.
68 ->terminate_monitoring_process()) &&
1666 !force_all) {
1667 if (error == 1) {
1668 return ER_STOP_REPLICA_MONITOR_IO_THREAD_TIMEOUT;
1669 }
1670 return error;
1671 }
1672 }
1673
1674
2/2
✓ Branch 0 taken 8583 times.
✓ Branch 1 taken 2926 times.
11509 if (thread_mask & (SLAVE_IO | SLAVE_FORCE_ALL)) {
1675
3/8
✓ Branch 0 taken 8583 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8583 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8583 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8583 DBUG_PRINT("info", ("Terminating IO thread"));
1676 8583 mi->abort_slave = true;
1677
4/6
✓ Branch 0 taken 8583 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8581 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
8583 DBUG_EXECUTE_IF("pause_after_queue_event",
1678 { rpl_replica_debug_point(DBUG_RPL_S_PAUSE_QUEUE_EV); });
1679 /*
1680 If the I/O thread is running and waiting for disk space,
1681 the signal above will not make it to stop.
1682 */
1683 bool io_waiting_disk_space =
1684
4/4
✓ Branch 0 taken 6832 times.
✓ Branch 1 taken 1751 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6826 times.
8583 mi->slave_running && mi->info_thd->is_waiting_for_disk_space();
1685
1686 /*
1687 If we are shutting down the server and the I/O thread is waiting for
1688 disk space, tell the terminate_slave_thread to forcefully kill the I/O
1689 thread by sending a KILL_CONNECTION signal that will be listened by
1690 my_write function.
1691 */
1692 8583 bool force_io_stop =
1693
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8577 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
8583 io_waiting_disk_space && (thread_mask & SLAVE_FORCE_ALL);
1694
1695 // If not shutting down, let the user to decide to abort I/O thread or wait
1696
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8577 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
8583 if (io_waiting_disk_space && !force_io_stop) {
1697
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(WARNING_LEVEL, ER_STOP_SLAVE_IO_THREAD_DISK_SPACE,
1698 mi->get_channel());
1699
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 DBUG_EXECUTE_IF("simulate_io_thd_wait_for_disk_space", {
1700 rpl_replica_debug_point(DBUG_RPL_S_IO_WAIT_FOR_SPACE);
1701 });
1702 }
1703
1704
1/2
✓ Branch 0 taken 8583 times.
✗ Branch 1 not taken.
8583 if ((error = terminate_slave_thread(
1705 mi->info_thd, io_lock, &mi->stop_cond, &mi->slave_running,
1706
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8583 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8583 times.
8583 &total_stop_wait_timeout, need_lock_term, force_io_stop)) &&
1707 !force_all) {
1708 if (error == 1) {
1709 return ER_STOP_SLAVE_IO_THREAD_TIMEOUT;
1710 }
1711 return error;
1712 }
1713
1714 #ifndef NDEBUG
1715
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8580 times.
8583 if (force_io_stop) {
1716
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (DBUG_EVALUATE_IF("simulate_io_thd_wait_for_disk_space", 1, 0)) {
1717
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 DBUG_SET("-d,simulate_io_thd_wait_for_disk_space");
1718 }
1719 }
1720 #endif
1721
1722
1/2
✓ Branch 0 taken 8583 times.
✗ Branch 1 not taken.
8583 mysql_mutex_lock(log_lock);
1723
1724
3/8
✓ Branch 0 taken 8583 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8583 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8583 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8583 DBUG_PRINT("info", ("Flushing relay log and source info repository."));
1725
3/4
✓ Branch 0 taken 8583 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6631 times.
✓ Branch 3 taken 1952 times.
8583 if (current_thd)
1726
2/4
✓ Branch 0 taken 6631 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6631 times.
✗ Branch 3 not taken.
6631 THD_STAGE_INFO(current_thd,
1727 stage_flushing_relay_log_and_source_info_repository);
1728
1729 /*
1730 Flushes the master info regardless of the sync_source_info option and
1731 GTID_ONLY = 0 for this channel
1732 */
1733
3/4
✓ Branch 0 taken 8583 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7312 times.
✓ Branch 3 taken 1271 times.
8583 if (!mi->is_gtid_only_mode()) {
1734
1/2
✓ Branch 0 taken 7312 times.
✗ Branch 1 not taken.
7312 mysql_mutex_lock(&mi->data_lock);
1735
3/4
✓ Branch 0 taken 7312 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7310 times.
7312 if (mi->flush_info(true)) {
1736
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 mysql_mutex_unlock(&mi->data_lock);
1737
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 mysql_mutex_unlock(log_lock);
1738 2 return ER_ERROR_DURING_FLUSH_LOGS;
1739 }
1740
1/2
✓ Branch 0 taken 7310 times.
✗ Branch 1 not taken.
7310 mysql_mutex_unlock(&mi->data_lock);
1741 }
1742 /*
1743 Flushes the relay log regardless of the sync_relay_log option.
1744 */
1745
3/4
✓ Branch 0 taken 8571 times.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8581 times.
17152 if (mi->rli->relay_log.is_open() &&
1746
2/4
✓ Branch 0 taken 8571 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8571 times.
8571 mi->rli->relay_log.flush_and_sync(true)) {
1747 mysql_mutex_unlock(log_lock);
1748 return ER_ERROR_DURING_FLUSH_LOGS;
1749 }
1750
1751
1/2
✓ Branch 0 taken 8581 times.
✗ Branch 1 not taken.
8581 mysql_mutex_unlock(log_lock);
1752 }
1753 11507 return 0;
1754 19422 }
1755
1756 /**
1757 Wait for a slave thread to terminate.
1758
1759 This function is called after requesting the thread to terminate
1760 (by setting @c abort_slave member of @c Relay_log_info or @c
1761 Master_info structure to 1). Termination of the thread is
1762 controlled with the the predicate <code>*slave_running</code>.
1763
1764 Function will acquire @c term_lock before waiting on the condition
1765 unless @c need_lock_term is false in which case the mutex should be
1766 owned by the caller of this function and will remain acquired after
1767 return from the function.
1768
1769 @param thd
1770 Current session.
1771 @param term_lock
1772 Associated lock to use when waiting for @c term_cond
1773
1774 @param term_cond
1775 Condition that is signalled when the thread has terminated
1776
1777 @param slave_running
1778 Pointer to predicate to check for slave thread termination
1779
1780 @param stop_wait_timeout
1781 A pointer to a variable that denotes the time the thread has
1782 to stop before we time out and throw an error.
1783
1784 @param need_lock_term
1785 If @c false the lock will not be acquired before waiting on
1786 the condition. In this case, it is assumed that the calling
1787 function acquires the lock before calling this function.
1788
1789 @param force
1790 Force the slave thread to stop by sending a KILL_CONNECTION
1791 signal to it. This is used to forcefully stop the I/O thread
1792 when it is waiting for disk space and the server is shutting
1793 down.
1794
1795 @retval 0 All OK, 1 on "STOP SLAVE" command timeout,
1796 ER_SLAVE_CHANNEL_NOT_RUNNING otherwise.
1797
1798 @note If the executing thread has to acquire term_lock
1799 (need_lock_term is true, the negative running status does not
1800 represent any issue therefore no error is reported.
1801
1802 */
1803 19302 static int terminate_slave_thread(THD *thd, mysql_mutex_t *term_lock,
1804 mysql_cond_t *term_cond,
1805 std::atomic<uint> *slave_running,
1806 ulong *stop_wait_timeout, bool need_lock_term,
1807 bool force) {
1808
1/2
✓ Branch 0 taken 19302 times.
✗ Branch 1 not taken.
19302 DBUG_TRACE;
1809
2/2
✓ Branch 0 taken 3904 times.
✓ Branch 1 taken 15398 times.
19302 if (need_lock_term) {
1810
1/2
✓ Branch 0 taken 3904 times.
✗ Branch 1 not taken.
3904 mysql_mutex_lock(term_lock);
1811 } else {
1812 15398 mysql_mutex_assert_owner(term_lock);
1813 }
1814
2/2
✓ Branch 0 taken 3525 times.
✓ Branch 1 taken 15777 times.
19302 if (!*slave_running) {
1815
1/2
✓ Branch 0 taken 3525 times.
✗ Branch 1 not taken.
3525 if (need_lock_term) {
1816 /*
1817 if run_lock (term_lock) is acquired locally then either
1818 slave_running status is fine
1819 */
1820
1/2
✓ Branch 0 taken 3525 times.
✗ Branch 1 not taken.
3525 mysql_mutex_unlock(term_lock);
1821 3525 return 0;
1822 } else {
1823 return ER_SLAVE_CHANNEL_NOT_RUNNING;
1824 }
1825 }
1826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15777 times.
15777 assert(thd != nullptr);
1827
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15777 times.
15777 THD_CHECK_SENTRY(thd);
1828
1829 /*
1830 Is is critical to test if the slave is running. Otherwise, we might
1831 be referening freed memory trying to kick it
1832 */
1833
1834
2/2
✓ Branch 0 taken 16156 times.
✓ Branch 1 taken 15769 times.
31925 while (*slave_running) // Should always be true
1835 {
1836
3/8
✓ Branch 0 taken 16156 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16156 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 16156 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
16156 DBUG_PRINT("loop", ("killing slave thread"));
1837
1838
1/2
✓ Branch 0 taken 16156 times.
✗ Branch 1 not taken.
16156 mysql_mutex_lock(&thd->LOCK_thd_data);
1839 /*
1840 Error codes from pthread_kill are:
1841 EINVAL: invalid signal number (can't happen)
1842 ESRCH: thread already killed (can happen, should be ignored)
1843 */
1844 #ifndef _WIN32
1845 16156 int err [[maybe_unused]] = pthread_kill(thd->real_id, SIGALRM);
1846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16156 times.
16156 assert(err != EINVAL);
1847 #endif
1848
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16153 times.
16156 if (force)
1849
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 thd->awake(THD::KILL_CONNECTION);
1850 else
1851
1/2
✓ Branch 0 taken 16153 times.
✗ Branch 1 not taken.
16153 thd->awake(THD::NOT_KILLED);
1852
1/2
✓ Branch 0 taken 16156 times.
✗ Branch 1 not taken.
16156 mysql_mutex_unlock(&thd->LOCK_thd_data);
1853
1854
4/6
✓ Branch 0 taken 16156 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 16154 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
16156 DBUG_EXECUTE_IF("block_on_thread_stop_after_awake", {
1855 rpl_replica_debug_point(DBUG_RPL_R_WAIT_AFTER_AWAKE_ON_THREAD_STOP);
1856 });
1857
1858 /*
1859 There is a small chance that slave thread might miss the first
1860 alarm. To protect against it, resend the signal until it reacts
1861 */
1862 struct timespec abstime;
1863
1/2
✓ Branch 0 taken 16156 times.
✗ Branch 1 not taken.
16156 set_timespec(&abstime, 2);
1864 #ifndef NDEBUG
1865 int error =
1866 #endif
1867
1/2
✓ Branch 0 taken 16156 times.
✗ Branch 1 not taken.
16156 mysql_cond_timedwait(term_cond, term_lock, &abstime);
1868
2/2
✓ Branch 0 taken 16143 times.
✓ Branch 1 taken 13 times.
16156 if ((*stop_wait_timeout) >= 2)
1869 16143 (*stop_wait_timeout) = (*stop_wait_timeout) - 2;
1870
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
13 else if (*slave_running) {
1871
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8 if (need_lock_term) mysql_mutex_unlock(term_lock);
1872 8 return 1;
1873 }
1874
3/4
✓ Branch 0 taken 15769 times.
✓ Branch 1 taken 379 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15769 times.
16148 assert(error == ETIMEDOUT || error == 0);
1875 }
1876
1877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15769 times.
15769 assert(*slave_running == 0);
1878
1879
3/4
✓ Branch 0 taken 379 times.
✓ Branch 1 taken 15390 times.
✓ Branch 2 taken 379 times.
✗ Branch 3 not taken.
15769 if (need_lock_term) mysql_mutex_unlock(term_lock);
1880 15769 return 0;
1881 19302 }
1882
1883 17864 bool start_slave_thread(PSI_thread_key thread_key, my_start_routine h_func,
1884 mysql_mutex_t *start_lock, mysql_mutex_t *cond_lock,
1885 mysql_cond_t *start_cond,
1886 std::atomic<uint> *slave_running,
1887 std::atomic<ulong> *slave_run_id, Master_info *mi) {
1888 17864 bool is_error = false;
1889 17864 my_thread_handle th;
1890 ulong start_id;
1891
1/2
✓ Branch 0 taken 17864 times.
✗ Branch 1 not taken.
17864 DBUG_TRACE;
1892
1893
3/4
✓ Branch 0 taken 229 times.
✓ Branch 1 taken 17635 times.
✓ Branch 2 taken 229 times.
✗ Branch 3 not taken.
17864 if (start_lock) mysql_mutex_lock(start_lock);
1894
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 17858 times.
17864 if (!server_id) {
1895
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 if (start_cond) mysql_cond_broadcast(start_cond);
1896
9/18
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 6 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 6 times.
✗ Branch 17 not taken.
6 LogErr(ERROR_LEVEL, ER_RPL_SERVER_ID_MISSING, mi->get_for_channel_str());
1897
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_BAD_SLAVE, MYF(0));
1898 6 goto err;
1899 }
1900
1901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17858 times.
17858 if (*slave_running) {
1902 if (start_cond) mysql_cond_broadcast(start_cond);
1903 my_error(ER_SLAVE_CHANNEL_MUST_STOP, MYF(0), mi->get_channel());
1904 goto err;
1905 }
1906 17858 start_id = *slave_run_id;
1907
3/8
✓ Branch 0 taken 17858 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17858 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17858 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
17858 DBUG_PRINT("info", ("Creating new slave thread"));
1908
2/4
✓ Branch 0 taken 17858 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17858 times.
17858 if (mysql_thread_create(thread_key, &th, &connection_attrib, h_func,
1909 (void *)mi)) {
1910 LogErr(ERROR_LEVEL, ER_RPL_CANT_CREATE_SLAVE_THREAD,
1911 mi->get_for_channel_str());
1912 my_error(ER_SLAVE_THREAD, MYF(0));
1913 goto err;
1914 }
1915
3/4
✓ Branch 0 taken 17700 times.
✓ Branch 1 taken 158 times.
✓ Branch 2 taken 17700 times.
✗ Branch 3 not taken.
17858 if (start_cond && cond_lock) // caller has cond_lock
1916 {
1917
1/2
✓ Branch 0 taken 17700 times.
✗ Branch 1 not taken.
17700 THD *thd = current_thd;
1918
6/6
✓ Branch 0 taken 17700 times.
✓ Branch 1 taken 17629 times.
✓ Branch 2 taken 17629 times.
✓ Branch 3 taken 71 times.
✓ Branch 4 taken 17629 times.
✓ Branch 5 taken 17700 times.
35329 while (start_id == *slave_run_id && thd != nullptr) {
1919
3/8
✓ Branch 0 taken 17629 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17629 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17629 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
17629 DBUG_PRINT("sleep", ("Waiting for replica thread to start"));
1920 17629 PSI_stage_info saved_stage = {0, "", 0, ""};
1921
1/2
✓ Branch 0 taken 17629 times.
✗ Branch 1 not taken.
17629 thd->ENTER_COND(start_cond, cond_lock,
1922 &stage_waiting_for_replica_thread_to_start, &saved_stage);
1923 /*
1924 It is not sufficient to test this at loop bottom. We must test
1925 it after registering the mutex in enter_cond(). If the kill
1926 happens after testing of thd->killed and before the mutex is
1927 registered, we could otherwise go waiting though thd->killed is
1928 set.
1929 */
1930
2/4
✓ Branch 0 taken 17629 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17629 times.
✗ Branch 3 not taken.
17629 if (!thd->killed) mysql_cond_wait(start_cond, cond_lock);
1931
1/2
✓ Branch 0 taken 17629 times.
✗ Branch 1 not taken.
17629 mysql_mutex_unlock(cond_lock);
1932
1/2
✓ Branch 0 taken 17629 times.
✗ Branch 1 not taken.
17629 thd->EXIT_COND(&saved_stage);
1933
1/2
✓ Branch 0 taken 17629 times.
✗ Branch 1 not taken.
17629 mysql_mutex_lock(cond_lock); // re-acquire it
1934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17629 times.
17629 if (thd->killed) {
1935 my_error(thd->killed, MYF(0));
1936 goto err;
1937 }
1938 }
1939 }
1940
1941 17858 goto end;
1942 6 err:
1943 6 is_error = true;
1944 17864 end:
1945
1946
3/4
✓ Branch 0 taken 229 times.
✓ Branch 1 taken 17635 times.
✓ Branch 2 taken 229 times.
✗ Branch 3 not taken.
17864 if (start_lock) mysql_mutex_unlock(start_lock);
1947 17864 return is_error;
1948 17864 }
1949
1950 /*
1951 start_slave_threads()
1952
1953 NOTES
1954 SLAVE_FORCE_ALL is not implemented here on purpose since it does not make
1955 sense to do that for starting a slave--we always care if it actually
1956 started the threads that were not previously running
1957 */
1958
1959 11164 bool start_slave_threads(bool need_lock_slave, bool wait_for_start,
1960 Master_info *mi, int thread_mask) {
1961 11164 mysql_mutex_t *lock_io{nullptr}, *lock_sql{nullptr}, *lock_cond_io{nullptr},
1962 11164 *lock_cond_sql{nullptr};
1963 11164 mysql_cond_t *cond_io{nullptr}, *cond_sql{nullptr};
1964 11164 bool is_error{false};
1965
1/2
✓ Branch 0 taken 11164 times.
✗ Branch 1 not taken.
11164 DBUG_TRACE;
1966
2/4
✓ Branch 0 taken 11164 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11164 times.
11164 DBUG_EXECUTE_IF("uninitialized_source-info_structure", mi->inited = false;);
1967
1968
4/4
✓ Branch 0 taken 11163 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 11158 times.
11164 if (!mi->inited || !mi->rli->inited) {
1969
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 int error = (!mi->inited ? ER_SLAVE_MI_INIT_REPOSITORY
1970 : ER_SLAVE_RLI_INIT_REPOSITORY);
1971
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 Rpl_info *info = (!mi->inited ? mi : static_cast<Rpl_info *>(mi->rli));
1972
4/8
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
6 const char *prefix = current_thd ? ER_THD_NONCONST(current_thd, error)
1973 : ER_DEFAULT_NONCONST(error);
1974
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 info->report(ERROR_LEVEL,
1975
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 (!mi->inited ? ER_SERVER_SLAVE_MI_INIT_REPOSITORY
1976 : ER_SERVER_SLAVE_RLI_INIT_REPOSITORY),
1977 prefix, nullptr);
1978
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(error, MYF(0));
1979 6 return true;
1980 }
1981
1982
3/4
✓ Branch 0 taken 11158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 11146 times.
11158 if (check_replica_configuration_errors(mi, thread_mask)) return true;
1983
1984 /**
1985 SQL AFTER MTS GAPS has no effect when GTID_MODE=ON and SOURCE_AUTO_POS=1
1986 as no gaps information was collected.
1987 **/
1988
7/8
✓ Branch 0 taken 11146 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5059 times.
✓ Branch 3 taken 6087 times.
✓ Branch 4 taken 4798 times.
✓ Branch 5 taken 261 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 11145 times.
15944 if (global_gtid_mode.get() == Gtid_mode::ON && mi->is_auto_position() &&
1989
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4797 times.
4798 mi->rli->until_condition == Relay_log_info::UNTIL_SQL_AFTER_MTS_GAPS) {
1990
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (current_thd) {
1991 1 push_warning_printf(
1992
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 current_thd, Sql_condition::SL_WARNING,
1993 ER_WARN_SQL_AFTER_MTS_GAPS_GAP_NOT_CALCULATED,
1994
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 ER_THD(current_thd, ER_WARN_SQL_AFTER_MTS_GAPS_GAP_NOT_CALCULATED),
1995 mi->get_channel());
1996 }
1997 }
1998
1999
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 11067 times.
11146 if (need_lock_slave) {
2000 79 lock_io = &mi->run_lock;
2001 79 lock_sql = &mi->rli->run_lock;
2002 }
2003
2/2
✓ Branch 0 taken 11067 times.
✓ Branch 1 taken 79 times.
11146 if (wait_for_start) {
2004 11067 cond_io = &mi->start_cond;
2005 11067 cond_sql = &mi->rli->start_cond;
2006 11067 lock_cond_io = &mi->run_lock;
2007 11067 lock_cond_sql = &mi->rli->run_lock;
2008 }
2009
2010
2/2
✓ Branch 0 taken 7416 times.
✓ Branch 1 taken 3730 times.
11146 if (thread_mask & SLAVE_IO)
2011
1/2
✓ Branch 0 taken 7416 times.
✗ Branch 1 not taken.
7416 is_error = start_slave_thread(key_thread_replica_io, handle_slave_io,
2012 lock_io, lock_cond_io, cond_io,
2013 &mi->slave_running, &mi->slave_run_id, mi);
2014
2015
4/4
✓ Branch 0 taken 7414 times.
✓ Branch 1 taken 3730 times.
✓ Branch 2 taken 110 times.
✓ Branch 3 taken 7304 times.
18558 if (!is_error && (thread_mask & (SLAVE_IO | SLAVE_MONITOR)) &&
2016
4/4
✓ Branch 0 taken 11144 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 11073 times.
29704 mi->is_source_connection_auto_failover() &&
2017
4/6
✓ Branch 0 taken 110 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 110 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 73 times.
✓ Branch 5 taken 37 times.
110 !Source_IO_monitor::get_instance()->is_monitoring_process_running()) {
2018
2/4
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
73 is_error = Source_IO_monitor::get_instance()->launch_monitoring_process(
2019 key_thread_replica_monitor_io);
2020
2021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (is_error)
2022 terminate_slave_threads(mi, thread_mask & (SLAVE_IO | SLAVE_MONITOR),
2023 rpl_stop_replica_timeout, need_lock_slave);
2024 }
2025
2026
4/4
✓ Branch 0 taken 11144 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 10377 times.
✓ Branch 3 taken 767 times.
11146 if (!is_error && (thread_mask & SLAVE_SQL)) {
2027 /*
2028 MTS-recovery gaps gathering is placed onto common execution path
2029 for either START-SLAVE and --skip-start-replica= 0
2030 */
2031
2/2
✓ Branch 0 taken 2861 times.
✓ Branch 1 taken 7516 times.
10377 if (mi->rli->recovery_parallel_workers != 0) {
2032
2/4
✓ Branch 0 taken 2861 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2861 times.
2861 if (mts_recovery_groups(mi->rli)) {
2033 is_error = true;
2034 my_error(ER_MTS_RECOVERY_FAILURE, MYF(0));
2035 }
2036 }
2037
1/2
✓ Branch 0 taken 10377 times.
✗ Branch 1 not taken.
10377 if (!is_error)
2038 10377 is_error = start_slave_thread(
2039 key_thread_replica_sql, handle_slave_sql, lock_sql, lock_cond_sql,
2040
1/2
✓ Branch 0 taken 10377 times.
✗ Branch 1 not taken.
10377 cond_sql, &mi->rli->slave_running, &mi->rli->slave_run_id, mi);
2041
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10373 times.
10377 if (is_error)
2042
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 terminate_slave_threads(mi, thread_mask & (SLAVE_IO | SLAVE_MONITOR),
2043 rpl_stop_replica_timeout, need_lock_slave);
2044 }
2045 11146 return is_error;
2046 11164 }
2047
2048 /*
2049 Release slave threads at time of executing shutdown.
2050
2051 SYNOPSIS
2052 end_slave()
2053 */
2054
2055 10103 void end_slave() {
2056
1/2
✓ Branch 0 taken 10103 times.
✗ Branch 1 not taken.
10103 DBUG_TRACE;
2057
2058 10103 Master_info *mi = nullptr;
2059
2060 /*
2061 This is called when the server terminates, in close_connections().
2062 It terminates slave threads. However, some CHANGE MASTER etc may still be
2063 running presently. If a START SLAVE was in progress, the mutex lock below
2064 will make us wait until slave threads have started, and START SLAVE
2065 returns, then we terminate them here.
2066 */
2067
1/2
✓ Branch 0 taken 10103 times.
✗ Branch 1 not taken.
10103 channel_map.wrlock();
2068
2069 /* traverse through the map and terminate the threads */
2070
4/6
✓ Branch 0 taken 10103 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19960 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9857 times.
✓ Branch 5 taken 10103 times.
19960 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
2071 9857 it++) {
2072 9857 mi = it->second;
2073
2074
1/2
✓ Branch 0 taken 9857 times.
✗ Branch 1 not taken.
9857 if (mi)
2075
1/2
✓ Branch 0 taken 9857 times.
✗ Branch 1 not taken.
9857 terminate_slave_threads(mi, SLAVE_FORCE_ALL, rpl_stop_replica_timeout);
2076 }
2077
1/2
✓ Branch 0 taken 10103 times.
✗ Branch 1 not taken.
10103 channel_map.unlock();
2078 10103 }
2079
2080 /**
2081 Free all resources used by slave threads at time of executing shutdown.
2082 The routine must be called after all possible users of channel_map
2083 have left.
2084
2085 */
2086 10103 void delete_slave_info_objects() {
2087
1/2
✓ Branch 0 taken 10103 times.
✗ Branch 1 not taken.
10103 DBUG_TRACE;
2088
2089 10103 Master_info *mi = nullptr;
2090
2091
1/2
✓ Branch 0 taken 10103 times.
✗ Branch 1 not taken.
10103 channel_map.wrlock();
2092
2093
4/6
✓ Branch 0 taken 10103 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19960 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9857 times.
✓ Branch 5 taken 10103 times.
19960 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
2094 9857 it++) {
2095 9857 mi = it->second;
2096
2097
1/2
✓ Branch 0 taken 9857 times.
✗ Branch 1 not taken.
9857 if (mi) {
2098
1/2
✓ Branch 0 taken 9857 times.
✗ Branch 1 not taken.
9857 mi->channel_wrlock();
2099
1/2
✓ Branch 0 taken 9857 times.
✗ Branch 1 not taken.
9857 end_info(mi);
2100
2/4
✓ Branch 0 taken 9857 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9857 times.
✗ Branch 3 not taken.
9857 if (mi->rli) delete mi->rli;
2101
1/2
✓ Branch 0 taken 9857 times.
✗ Branch 1 not taken.
9857 delete mi;
2102 9857 it->second = 0;
2103 }
2104 }
2105
2106 // Clean other types of channel
2107
1/2
✓ Branch 0 taken 10103 times.
✗ Branch 1 not taken.
10103 for (mi_map::iterator it = channel_map.begin(GROUP_REPLICATION_CHANNEL);
2108
3/4
✓ Branch 0 taken 11620 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1517 times.
✓ Branch 3 taken 10103 times.
11620 it != channel_map.end(GROUP_REPLICATION_CHANNEL); it++) {
2109 1517 mi = it->second;
2110
2111
1/2
✓ Branch 0 taken 1517 times.
✗ Branch 1 not taken.
1517 if (mi) {
2112
1/2
✓ Branch 0 taken 1517 times.
✗ Branch 1 not taken.
1517 mi->channel_wrlock();
2113
1/2
✓ Branch 0 taken 1517 times.
✗ Branch 1 not taken.
1517 end_info(mi);
2114
2/4
✓ Branch 0 taken 1517 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1517 times.
✗ Branch 3 not taken.
1517 if (mi->rli) delete mi->rli;
2115
1/2
✓ Branch 0 taken 1517 times.
✗ Branch 1 not taken.
1517 delete mi;
2116 1517 it->second = 0;
2117 }
2118 }
2119
2120
1/2
✓ Branch 0 taken 10103 times.
✗ Branch 1 not taken.
10103 channel_map.unlock();
2121 10103 }
2122
2123 /**
2124 Check if multi-statement transaction mode and master and slave info
2125 repositories are set to table.
2126
2127 @param thd THD object
2128
2129 @retval true Success
2130 @retval false Failure
2131 */
2132 61276 static bool is_autocommit_off_and_infotables(THD *thd) {
2133
1/2
✓ Branch 0 taken 61276 times.
✗ Branch 1 not taken.
61276 DBUG_TRACE;
2134
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 57722 times.
57734 return (thd && thd->in_multi_stmt_transaction_mode() &&
2135 12 (opt_mi_repository_id == INFO_REPOSITORY_TABLE ||
2136 opt_rli_repository_id == INFO_REPOSITORY_TABLE))
2137
3/4
✓ Branch 0 taken 57734 times.
✓ Branch 1 taken 3542 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
119010 ? true
2138 61276 : false;
2139 61276 }
2140
2141 407 static bool monitor_io_replica_killed(THD *thd, Master_info *mi) {
2142 407 return Source_IO_monitor::get_instance()->is_monitor_killed(thd, mi);
2143 }
2144
2145 3153114 static bool io_slave_killed(THD *thd, Master_info *mi) {
2146
1/2
✓ Branch 0 taken 3153113 times.
✗ Branch 1 not taken.
3153114 DBUG_TRACE;
2147
2148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3153113 times.
3153113 assert(mi->info_thd == thd);
2149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3153113 times.
3153113 assert(mi->slave_running); // tracking buffer overrun
2150
5/6
✓ Branch 0 taken 3146055 times.
✓ Branch 1 taken 7058 times.
✓ Branch 2 taken 3146055 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✓ Branch 5 taken 3145836 times.
6306227 return mi->abort_slave || connection_events_loop_aborted() || thd->killed;
2151 3153113 }
2152
2153 /**
2154 The function analyzes a possible killed status and makes
2155 a decision whether to accept it or not.
2156 Normally upon accepting the sql thread goes to shutdown.
2157 In the event of deferring decision @c rli->last_event_start_time waiting
2158 timer is set to force the killed status be accepted upon its expiration.
2159
2160 Notice Multi-Threaded-Slave behaves similarly in that when it's being
2161 stopped and the current group of assigned events has not yet scheduled
2162 completely, Coordinator defers to accept to leave its read-distribute
2163 state. The above timeout ensures waiting won't last endlessly, and in
2164 such case an error is reported.
2165
2166 @param thd pointer to a THD instance
2167 @param rli pointer to Relay_log_info instance
2168
2169 @return true the killed status is recognized, false a possible killed
2170 status is deferred.
2171 */
2172 18588011 bool sql_slave_killed(THD *thd, Relay_log_info *rli) {
2173 18588011 bool is_parallel_warn = false;
2174
2175
1/2
✓ Branch 0 taken 18588013 times.
✗ Branch 1 not taken.
18588011 DBUG_TRACE;
2176
2177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18588013 times.
18588013 assert(rli->info_thd == thd);
2178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18588013 times.
18588013 assert(rli->slave_running == 1);
2179
2/2
✓ Branch 0 taken 26020 times.
✓ Branch 1 taken 18561993 times.
18588013 if (rli->sql_thread_kill_accepted) return true;
2180
5/8
✓ Branch 0 taken 18561991 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 18561990 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
18561993 DBUG_EXECUTE_IF("stop_when_mta_in_group", rli->abort_slave = 1;
2181 DBUG_SET("-d,stop_when_mta_in_group");
2182 DBUG_SET("-d,simulate_stop_when_mta_in_group");
2183 return false;);
2184
8/8
✓ Branch 0 taken 18561733 times.
✓ Branch 1 taken 257 times.
✓ Branch 2 taken 18560896 times.
✓ Branch 3 taken 837 times.
✓ Branch 4 taken 14964 times.
✓ Branch 5 taken 18545932 times.
✓ Branch 6 taken 16058 times.
✓ Branch 7 taken 18545932 times.
18561990 if (connection_events_loop_aborted() || thd->killed || rli->abort_slave) {
2185 16058 rli->sql_thread_kill_accepted = true;
2186 /* NOTE: In MTS mode if all workers are done and if the partial trx
2187 (if any) can be rolled back safely we can accept the kill */
2188 const bool cannot_rollback =
2189
3/4
✓ Branch 0 taken 16058 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6248 times.
✓ Branch 3 taken 9810 times.
22306 rli->is_mts_in_group() &&
2190
5/6
✓ Branch 0 taken 6222 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 6222 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 348 times.
✓ Branch 5 taken 5874 times.
6248 (!rli->abort_slave || !rli->mts_workers_queue_empty() ||
2191
3/4
✓ Branch 0 taken 348 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 194 times.
✓ Branch 3 taken 154 times.
348 rli->cannot_safely_rollback());
2192
2193 16058 is_parallel_warn =
2194
7/8
✓ Branch 0 taken 16058 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16016 times.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 9922 times.
✓ Branch 5 taken 6094 times.
✓ Branch 6 taken 785 times.
✓ Branch 7 taken 9137 times.
16058 (rli->is_parallel_exec() && (cannot_rollback || thd->killed));
2195 /*
2196 Slave can execute stop being in one of two MTS or Single-Threaded mode.
2197 The modes define different criteria to accept the stop.
2198 In particular that relates to the concept of groupping.
2199 Killed Coordinator thread expects the worst so it warns on
2200 possible consistency issue.
2201 */
2202
8/10
✓ Branch 0 taken 9179 times.
✓ Branch 1 taken 6879 times.
✓ Branch 2 taken 9179 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
✓ Branch 5 taken 9137 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 42 times.
✓ Branch 8 taken 6879 times.
✓ Branch 9 taken 9179 times.
16100 if (is_parallel_warn || (!rli->is_parallel_exec() &&
2203 42 thd->get_transaction()->cannot_safely_rollback(
2204 Transaction_ctx::SESSION) &&
2205 rli->is_in_group())) {
2206 6879 char msg_stopped[] =
2207 "... Slave SQL Thread stopped with incomplete event group "
2208 "having non-transactional changes. "
2209 "If the group consists solely of row-based events, you can try "
2210 "to restart the slave with --replica-exec-mode=IDEMPOTENT, which "
2211 "ignores duplicate key, key not found, and similar errors (see "
2212 "documentation for details).";
2213 6879 char msg_stopped_mts[] =
2214 "... The slave coordinator and worker threads are stopped, possibly "
2215 "leaving data in inconsistent state. A restart should "
2216 "restore consistency automatically, although using non-transactional "
2217 "storage for data or info tables or DDL queries could lead to "
2218 "problems. "
2219 "In such cases you have to examine your data (see documentation for "
2220 "details).";
2221
2222
2/2
✓ Branch 0 taken 6112 times.
✓ Branch 1 taken 767 times.
6879 if (rli->abort_slave) {
2223
3/8
✓ Branch 0 taken 6112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6112 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6112 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
6112 DBUG_PRINT("info",
2224 ("Request to stop slave SQL Thread received while "
2225 "applying an MTS group or a group that "
2226 "has non-transactional "
2227 "changes; waiting for completion of the group ... "));
2228
2229 /*
2230 Slave sql thread shutdown in face of unfinished group modified
2231 Non-trans table is handled via a timer. The slave may eventually
2232 give out to complete the current group and in that case there
2233 might be issues at consequent slave restart, see the error message.
2234 WL#2975 offers a robust solution requiring to store the last exectuted
2235 event's coordinates along with the group's coordianates
2236 instead of waiting with @c last_event_start_time the timer.
2237 */
2238
2239
2/2
✓ Branch 0 taken 291 times.
✓ Branch 1 taken 5821 times.
6112 if (rli->last_event_start_time == 0)
2240 291 rli->last_event_start_time = time(nullptr);
2241 6112 rli->sql_thread_kill_accepted =
2242 6112 difftime(time(nullptr), rli->last_event_start_time) <=
2243 SLAVE_WAIT_GROUP_DONE
2244 6112 ? false
2245 : true;
2246
2247
5/8
✓ Branch 0 taken 6112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6110 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
6112 DBUG_EXECUTE_IF("stop_replica_middle_group",
2248 DBUG_EXECUTE_IF("incomplete_group_in_relay_log",
2249 rli->sql_thread_kill_accepted =
2250 true;);); // time is over
2251
2252
4/4
✓ Branch 0 taken 6110 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 222 times.
✓ Branch 3 taken 5888 times.
6112 if (!rli->sql_thread_kill_accepted && !rli->reported_unsafe_warning) {
2253
2/4
✓ Branch 0 taken 222 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 222 times.
✗ Branch 3 not taken.
222 rli->report(
2254 WARNING_LEVEL, 0,
2255 !is_parallel_warn
2256 ? "Request to stop slave SQL Thread received while "
2257 "applying a group that has non-transactional "
2258 "changes; waiting for completion of the group ... "
2259 : "Coordinator thread of multi-threaded slave is being "
2260 "stopped in the middle of assigning a group of events; "
2261 "deferring to exit until the group completion ... ");
2262 222 rli->reported_unsafe_warning = true;
2263 }
2264 }
2265
2/2
✓ Branch 0 taken 769 times.
✓ Branch 1 taken 6110 times.
6879 if (rli->sql_thread_kill_accepted) {
2266
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 741 times.
769 if (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP) {
2267 28 rli->mts_group_status = Relay_log_info::MTS_KILLED_GROUP;
2268 }
2269
1/2
✓ Branch 0 taken 769 times.
✗ Branch 1 not taken.
769 if (is_parallel_warn)
2270
4/6
✓ Branch 0 taken 769 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 764 times.
✓ Branch 4 taken 769 times.
✗ Branch 5 not taken.
769 rli->report(!rli->is_error()
2271 ? ERROR_LEVEL
2272 : WARNING_LEVEL, // an error was reported by Worker
2273 ER_MTS_INCONSISTENT_DATA,
2274 ER_THD(thd, ER_MTS_INCONSISTENT_DATA), msg_stopped_mts);
2275 else
2276 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
2277 ER_THD(thd, ER_SLAVE_FATAL_ERROR), msg_stopped);
2278 }
2279 }
2280 }
2281
2282
2/2
✓ Branch 0 taken 9948 times.
✓ Branch 1 taken 18552042 times.
18561990 if (rli->sql_thread_kill_accepted) rli->last_event_start_time = 0;
2283
2284 18561990 return rli->sql_thread_kill_accepted;
2285 18588011 }
2286
2287 1274 bool net_request_file(NET *net, const char *fname) {
2288
1/2
✓ Branch 0 taken 1274 times.
✗ Branch 1 not taken.
1274 DBUG_TRACE;
2289
1/2
✓ Branch 0 taken 1274 times.
✗ Branch 1 not taken.
1274 return net_write_command(net, 251, pointer_cast<const uchar *>(fname),
2290 2548 strlen(fname), pointer_cast<const uchar *>(""), 0);
2291 1274 }
2292
2293 /*
2294 From other comments and tests in code, it looks like
2295 sometimes Query_log_event and Load_log_event can have db == 0
2296 (see rewrite_db() above for example)
2297 (cases where this happens are unclear; it may be when the master is 3.23).
2298 */
2299
2300 305 const char *print_slave_db_safe(const char *db) {
2301
1/2
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
305 DBUG_TRACE;
2302
2303
1/2
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
610 return (db ? db : "");
2304 305 }
2305
2306 7404 bool is_network_error(uint errorno) {
2307
3/4
✓ Branch 0 taken 7231 times.
✓ Branch 1 taken 173 times.
✓ Branch 2 taken 7231 times.
✗ Branch 3 not taken.
7404 return errorno == CR_CONNECTION_ERROR || errorno == CR_CONN_HOST_ERROR ||
2308
3/4
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 6794 times.
✓ Branch 2 taken 437 times.
✗ Branch 3 not taken.
7231 errorno == CR_SERVER_GONE_ERROR || errorno == CR_SERVER_LOST ||
2309
3/4
✓ Branch 0 taken 437 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 430 times.
✓ Branch 3 taken 7 times.
437 errorno == ER_CON_COUNT_ERROR || errorno == ER_SERVER_SHUTDOWN ||
2310
2/4
✓ Branch 0 taken 7404 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 430 times.
14808 errorno == ER_NET_READ_INTERRUPTED ||
2311 7404 errorno == ER_NET_WRITE_INTERRUPTED;
2312 }
2313
2314 enum enum_command_status {
2315 COMMAND_STATUS_OK,
2316 COMMAND_STATUS_ERROR,
2317 COMMAND_STATUS_ALLOWED_ERROR
2318 };
2319 /**
2320 Execute an initialization query for the IO thread.
2321
2322 If there is an error, then this function calls mysql_free_result;
2323 otherwise the MYSQL object holds the result after this call. If
2324 there is an error other than allowed_error, then this function
2325 prints a message and returns -1.
2326
2327 @param mi Master_info object.
2328 @param query Query string.
2329 @param allowed_error Allowed error code, or 0 if no errors are allowed.
2330 @param[out] master_res If this is not NULL and there is no error, then
2331 mysql_store_result() will be called and the result stored in this pointer.
2332 @param[out] master_row If this is not NULL and there is no error, then
2333 mysql_fetch_row() will be called and the result stored in this pointer.
2334
2335 @retval COMMAND_STATUS_OK No error.
2336 @retval COMMAND_STATUS_ALLOWED_ERROR There was an error and the
2337 error code was 'allowed_error'.
2338 @retval COMMAND_STATUS_ERROR There was an error and the error code
2339 was not 'allowed_error'.
2340 */
2341 7594 static enum_command_status io_thread_init_command(
2342 Master_info *mi, const char *query, int allowed_error,
2343 MYSQL_RES **master_res = nullptr, MYSQL_ROW *master_row = nullptr) {
2344
1/2
✓ Branch 0 taken 7594 times.
✗ Branch 1 not taken.
7594 DBUG_TRACE;
2345
3/8
✓ Branch 0 taken 7594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7594 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7594 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7594 DBUG_PRINT("info", ("IO thread initialization command: '%s'", query));
2346 7594 MYSQL *mysql = mi->mysql;
2347
1/2
✓ Branch 0 taken 7594 times.
✗ Branch 1 not taken.
7594 int ret = mysql_real_query(mysql, query, static_cast<ulong>(strlen(query)));
2348
3/4
✓ Branch 0 taken 7594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7593 times.
7594 if (io_slave_killed(mi->info_thd, mi)) {
2349
9/18
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
1 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_IO_THREAD_WAS_KILLED,
2350 mi->get_for_channel_str(), query);
2351
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 mysql_free_result(mysql_store_result(mysql));
2352 1 return COMMAND_STATUS_ERROR;
2353 }
2354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7593 times.
7593 if (ret != 0) {
2355 uint err{mysql_errno(mysql)};
2356 mysql_free_result(mysql_store_result(mysql));
2357 if (is_network_error(err)) mi->set_network_error();
2358 if (!err || (int)err != allowed_error) {
2359 mi->report(is_network_error(err) ? WARNING_LEVEL : ERROR_LEVEL, err,
2360 "The slave IO thread stops because the initialization query "
2361 "'%s' failed with error '%s'.",
2362 query, mysql_error(mysql));
2363 return COMMAND_STATUS_ERROR;
2364 }
2365 return COMMAND_STATUS_ALLOWED_ERROR;
2366 }
2367
1/2
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
7593 if (master_res != nullptr) {
2368
2/4
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7593 times.
7593 if ((*master_res = mysql_store_result(mysql)) == nullptr) {
2369 uint err{mysql_errno(mysql)};
2370 if (is_network_error(err)) mi->set_network_error();
2371 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2372 "The slave IO thread stops because the initialization query "
2373 "'%s' did not return any result.",
2374 query);
2375 return COMMAND_STATUS_ERROR;
2376 }
2377
1/2
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
7593 if (master_row != nullptr) {
2378
2/4
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7593 times.
7593 if ((*master_row = mysql_fetch_row(*master_res)) == nullptr) {
2379 uint err{mysql_errno(mysql)};
2380 if (is_network_error(err)) mi->set_network_error();
2381 mysql_free_result(*master_res);
2382 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2383 "The slave IO thread stops because the initialization query "
2384 "'%s' did not return any row.",
2385 query);
2386 return COMMAND_STATUS_ERROR;
2387 }
2388 }
2389 } else
2390 assert(master_row == nullptr);
2391 7593 return COMMAND_STATUS_OK;
2392 7594 }
2393
2394 /**
2395 Set user variables after connecting to the master.
2396
2397 @param mysql MYSQL to request uuid from master.
2398 @param mi Master_info to set master_uuid
2399
2400 @return 0: Success, 1: Fatal error, 2: Transient network error.
2401 */
2402 7548 int io_thread_init_commands(MYSQL *mysql, Master_info *mi) {
2403 char query[256];
2404 7548 int ret = 0;
2405
3/4
✓ Branch 0 taken 7548 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7546 times.
7548 DBUG_EXECUTE_IF("fake_5_5_version_replica", return ret;);
2406
2407 7546 mi->reset_network_error();
2408
2409 7546 sprintf(query, "SET @slave_uuid = '%s', @replica_uuid = '%s'", server_uuid,
2410 server_uuid);
2411
3/6
✓ Branch 0 taken 7546 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7546 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7546 times.
7546 if (mysql_real_query(mysql, query, static_cast<ulong>(strlen(query))) &&
2412 !check_io_slave_killed(mi->info_thd, mi, nullptr))
2413 goto err;
2414
2415
2/4
✓ Branch 0 taken 7546 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7546 times.
✗ Branch 3 not taken.
7546 mysql_free_result(mysql_store_result(mysql));
2416 7546 return ret;
2417
2418 err:
2419 if (mysql_errno(mysql) && is_network_error(mysql_errno(mysql))) {
2420 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2421 "The initialization command '%s' failed with the following"
2422 " error: '%s'.",
2423 query, mysql_error(mysql));
2424 mi->set_network_error();
2425 ret = 2;
2426 } else {
2427 char errmsg[512];
2428 const char *errmsg_fmt =
2429 "The slave I/O thread stops because a fatal error is encountered "
2430 "when it tries to send query to master(query: %s).";
2431
2432 sprintf(errmsg, errmsg_fmt, query);
2433 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
2434 ER_THD(current_thd, ER_SLAVE_FATAL_ERROR), errmsg);
2435 ret = 1;
2436 }
2437 mysql_free_result(mysql_store_result(mysql));
2438 return ret;
2439 }
2440
2441 /**
2442 Get master's uuid on connecting.
2443
2444 @param mysql MYSQL to request uuid from master.
2445 @param mi Master_info to set master_uuid
2446
2447 @return 0: Success, 1: Fatal error, 2: Transient network error.
2448 */
2449 7550 static int get_master_uuid(MYSQL *mysql, Master_info *mi) {
2450 const char *errmsg;
2451 7550 MYSQL_RES *master_res = nullptr;
2452 7550 MYSQL_ROW master_row = nullptr;
2453 7550 int ret = 0;
2454 7550 char query_buf[] = "SELECT @@GLOBAL.SERVER_UUID";
2455
2456 7550 mi->reset_network_error();
2457
2458
3/4
✓ Branch 0 taken 7550 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7549 times.
7550 DBUG_EXECUTE_IF("dbug.return_null_SOURCE_UUID", {
2459 mi->master_uuid[0] = 0;
2460 return 0;
2461 };);
2462
2463
4/6
✓ Branch 0 taken 7549 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 7545 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
7549 DBUG_EXECUTE_IF("dbug.before_get_SOURCE_UUID",
2464 { rpl_replica_debug_point(DBUG_RPL_S_BEFORE_MASTER_UUID); };);
2465
2466
2/6
✓ Branch 0 taken 7549 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7549 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
7549 DBUG_EXECUTE_IF("dbug.simulate_busy_io",
2467 { rpl_replica_debug_point(DBUG_RPL_S_SIMULATE_BUSY_IO); };);
2468 #ifndef NDEBUG
2469
3/4
✓ Branch 0 taken 7549 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7548 times.
7549 DBUG_EXECUTE_IF("dbug.simulate_no_such_var_server_uuid", {
2470 query_buf[strlen(query_buf) - 1] = '_'; // corrupt the last char
2471 });
2472 #endif
2473
1/2
✓ Branch 0 taken 7549 times.
✗ Branch 1 not taken.
7549 if (!mysql_real_query(mysql, STRING_WITH_LEN(query_buf)) &&
2474
6/8
✓ Branch 0 taken 7547 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7547 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7547 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7547 times.
✓ Branch 7 taken 2 times.
15096 (master_res = mysql_store_result(mysql)) &&
2475
2/4
✓ Branch 0 taken 7547 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7547 times.
✗ Branch 3 not taken.
7547 (master_row = mysql_fetch_row(master_res))) {
2476
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7539 times.
7547 if (!strcmp(::server_uuid, master_row[0]) &&
2477
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 !mi->rli->replicate_same_server_id) {
2478 1 errmsg =
2479 "The slave I/O thread stops because master and slave have equal "
2480 "MySQL server UUIDs; these UUIDs must be different for "
2481 "replication to work.";
2482
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
2483
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 ER_THD(current_thd, ER_SLAVE_FATAL_ERROR), errmsg);
2484 // Fatal error
2485 1 ret = 1;
2486 } else {
2487
4/4
✓ Branch 0 taken 2735 times.
✓ Branch 1 taken 4811 times.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 2676 times.
7546 if (mi->master_uuid[0] != 0 && strcmp(mi->master_uuid, master_row[0]))
2488
8/16
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 59 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 59 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 59 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 59 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 59 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 59 times.
✗ Branch 15 not taken.
59 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_MASTER_UUID_HAS_CHANGED,
2489 mi->master_uuid);
2490 7546 strncpy(mi->master_uuid, master_row[0], UUID_LENGTH);
2491 7546 mi->master_uuid[UUID_LENGTH] = 0;
2492 }
2493
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 } else if (mysql_errno(mysql) != ER_UNKNOWN_SYSTEM_VARIABLE) {
2494
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 if (is_network_error(mysql_errno(mysql))) {
2495
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2496 "Get master SERVER_UUID failed with error: %s",
2497 mysql_error(mysql));
2498 1 mi->set_network_error();
2499 1 ret = 2;
2500 } else {
2501 /* Fatal error */
2502 errmsg =
2503 "The slave I/O thread stops because a fatal error is encountered "
2504 "when it tries to get the value of SERVER_UUID variable from master.";
2505 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
2506 ER_THD(current_thd, ER_SLAVE_FATAL_ERROR), errmsg);
2507 ret = 1;
2508 }
2509 } else {
2510 1 mi->master_uuid[0] = 0;
2511
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mi->report(
2512 WARNING_LEVEL, ER_UNKNOWN_SYSTEM_VARIABLE,
2513 "Unknown system variable 'SERVER_UUID' on master. "
2514 "A probable cause is that the variable is not supported on the "
2515 "master (version: %s), even though it is on the slave (version: %s)",
2516 mysql->server_version, server_version);
2517 }
2518
2519
3/4
✓ Branch 0 taken 7547 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7547 times.
✗ Branch 3 not taken.
7549 if (master_res) mysql_free_result(master_res);
2520 7549 return ret;
2521 }
2522
2523 /*
2524 Note that we rely on the master's version (3.23, 4.0.14 etc) instead of
2525 relying on the binlog's version. This is not perfect: imagine an upgrade
2526 of the master without waiting that all slaves are in sync with the master;
2527 then a slave could be fooled about the binlog's format. This is what happens
2528 when people upgrade a 3.23 master to 4.0 without doing RESET MASTER: 4.0
2529 slaves are fooled. So we do this only to distinguish between 3.23 and more
2530 recent masters (it's too late to change things for 3.23).
2531
2532 RETURNS
2533 0 ok
2534 1 error
2535 2 transient network problem, the caller should try to reconnect
2536 */
2537
2538 7614 static int get_master_version_and_clock(MYSQL *mysql, Master_info *mi) {
2539 char err_buff[MAX_SLAVE_ERRMSG];
2540 7614 const char *errmsg = nullptr;
2541 7614 int err_code = 0;
2542 7614 int version_number = 0;
2543 7614 version_number = atoi(mysql->server_version);
2544
2545 7614 MYSQL_RES *master_res = nullptr;
2546 MYSQL_ROW master_row;
2547
1/2
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
7614 DBUG_TRACE;
2548
2549
2/4
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7614 times.
7614 DBUG_EXECUTE_IF("unrecognized_source_version", { version_number = 1; };);
2550
2551 7614 mi->reset_network_error();
2552
2553
2/4
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7614 times.
7614 if (!my_isdigit(&my_charset_bin, *mysql->server_version) ||
2554 version_number < 5) {
2555 errmsg = "Master reported unrecognized MySQL version";
2556 err_code = ER_SLAVE_FATAL_ERROR;
2557 sprintf(err_buff, ER_THD_NONCONST(current_thd, err_code), errmsg);
2558 goto err;
2559 }
2560
2561
1/2
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
7614 mysql_mutex_lock(mi->rli->relay_log.get_log_lock());
2562
1/2
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
7614 mysql_mutex_lock(&mi->data_lock);
2563
3/6
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7614 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7614 times.
✗ Branch 5 not taken.
7614 mi->set_mi_description_event(new Format_description_log_event());
2564 /* as we are here, we tried to allocate the event */
2565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7614 times.
7614 if (mi->get_mi_description_event() == nullptr) {
2566 mysql_mutex_unlock(&mi->data_lock);
2567 mysql_mutex_unlock(mi->rli->relay_log.get_log_lock());
2568 errmsg = "default Format_description_log_event";
2569 err_code = ER_SLAVE_CREATE_EVENT_FAILURE;
2570 sprintf(err_buff, ER_THD_NONCONST(current_thd, err_code), errmsg);
2571 goto err;
2572 }
2573
2574 /*
2575 FD_q's (A) is set initially from RL's (A): FD_q.(A) := RL.(A).
2576 It's necessary to adjust FD_q.(A) at this point because in the following
2577 course FD_q is going to be dumped to RL.
2578 Generally FD_q is derived from a received FD_m (roughly FD_q := FD_m)
2579 in queue_event and the master's (A) is installed.
2580 At one step with the assignment the Relay-Log's checksum alg is set to
2581 a new value: RL.(A) := FD_q.(A). If the slave service is stopped
2582 the last time assigned RL.(A) will be passed over to the restarting
2583 service (to the current execution point).
2584 RL.A is a "codec" to verify checksum in queue_event() almost all the time
2585 the first fake Rotate event.
2586 Starting from this point IO thread will executes the following checksum
2587 warmup sequence of actions:
2588
2589 FD_q.A := RL.A,
2590 A_m^0 := master.@@global.binlog_checksum,
2591 {queue_event(R_f): verifies(R_f, A_m^0)},
2592 {queue_event(FD_m): verifies(FD_m, FD_m.A), dump(FD_q), rotate(RL),
2593 FD_q := FD_m, RL.A := FD_q.A)}
2594
2595 See legends definition on MYSQL_BIN_LOG::relay_log_checksum_alg
2596 docs lines (binlog.h).
2597 In above A_m^0 - the value of master's
2598 @@binlog_checksum determined in the upcoming handshake (stored in
2599 mi->checksum_alg_before_fd).
2600
2601
2602 After the warm-up sequence IO gets to "normal" checksum verification mode
2603 to use RL.A in
2604
2605 {queue_event(E_m): verifies(E_m, RL.A)}
2606
2607 until it has received a new FD_m.
2608 */
2609 15228 mi->get_mi_description_event()->common_footer->checksum_alg =
2610 7614 mi->rli->relay_log.relay_log_checksum_alg;
2611
2612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7614 times.
7614 assert(mi->get_mi_description_event()->common_footer->checksum_alg !=
2613 binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
2614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7614 times.
7614 assert(mi->rli->relay_log.relay_log_checksum_alg !=
2615 binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
2616
2617
1/2
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
7614 mysql_mutex_unlock(&mi->data_lock);
2618
1/2
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
7614 mysql_mutex_unlock(mi->rli->relay_log.get_log_lock());
2619
2620 /*
2621 Compare the master and slave's clock. Do not die if master's clock is
2622 unavailable (very old master not supporting UNIX_TIMESTAMP()?).
2623 */
2624
2625
4/6
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7613 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
7614 DBUG_EXECUTE_IF("dbug.before_get_UNIX_TIMESTAMP", {
2626 rpl_replica_debug_point(DBUG_RPL_S_BEFORE_UNIX_TIMESTAMP);
2627 };);
2628
2629 7614 master_res = nullptr;
2630
5/8
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7613 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
7614 DBUG_EXECUTE_IF("get_master_version.timestamp.ER_NET_READ_INTERRUPTED", {
2631 DBUG_SET("+d,inject_ER_NET_READ_INTERRUPTED");
2632 DBUG_SET(
2633 "-d,get_master_version.timestamp."
2634 "ER_NET_READ_INTERRUPTED");
2635 });
2636
1/2
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
7614 if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT UNIX_TIMESTAMP()")) &&
2637
6/8
✓ Branch 0 taken 7611 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 7611 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7611 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7611 times.
✓ Branch 7 taken 3 times.
15225 (master_res = mysql_store_result(mysql)) &&
2638
2/4
✓ Branch 0 taken 7611 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7611 times.
✗ Branch 3 not taken.
7611 (master_row = mysql_fetch_row(master_res))) {
2639
1/2
✓ Branch 0 taken 7611 times.
✗ Branch 1 not taken.
7611 mysql_mutex_lock(&mi->data_lock);
2640 7611 mi->clock_diff_with_master =
2641 7611 (long)(time((time_t *)nullptr) - strtoul(master_row[0], nullptr, 10));
2642
3/4
✓ Branch 0 taken 7611 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7609 times.
7611 DBUG_EXECUTE_IF("dbug.mta.force_clock_diff_eq_0",
2643 mi->clock_diff_with_master = 0;);
2644
1/2
✓ Branch 0 taken 7611 times.
✗ Branch 1 not taken.
7611 mysql_mutex_unlock(&mi->data_lock);
2645
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 } else if (check_io_slave_killed(mi->info_thd, mi, nullptr))
2646 1 goto slave_killed_err;
2647
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 else if (is_network_error(mysql_errno(mysql))) {
2648
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2649 "Get master clock failed with error: %s", mysql_error(mysql));
2650 2 goto network_err;
2651 } else {
2652 mysql_mutex_lock(&mi->data_lock);
2653 mi->clock_diff_with_master = 0; /* The "most sensible" value */
2654 mysql_mutex_unlock(&mi->data_lock);
2655 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_SECONDS_BEHIND_MASTER_DUBIOUS,
2656 mysql_error(mysql), mysql_errno(mysql));
2657 }
2658
1/2
✓ Branch 0 taken 7611 times.
✗ Branch 1 not taken.
7611 if (master_res) {
2659
1/2
✓ Branch 0 taken 7611 times.
✗ Branch 1 not taken.
7611 mysql_free_result(master_res);
2660 7611 master_res = nullptr;
2661 }
2662
2663 /*
2664 Check that the master's server id and ours are different. Because if they
2665 are equal (which can result from a simple copy of master's datadir to slave,
2666 thus copying some my.cnf), replication will work but all events will be
2667 skipped.
2668 Do not die if SELECT @@SERVER_ID fails on master (very old master?).
2669 Note: we could have put a @@SERVER_ID in the previous SELECT
2670 UNIX_TIMESTAMP() instead, but this would not have worked on 3.23 masters.
2671 */
2672
4/6
✓ Branch 0 taken 7611 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7610 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
7611 DBUG_EXECUTE_IF("dbug.before_get_SERVER_ID",
2673 { rpl_replica_debug_point(DBUG_RPL_S_BEFORE_SERVER_ID); };);
2674 7611 master_res = nullptr;
2675 7611 master_row = nullptr;
2676
5/8
✓ Branch 0 taken 7611 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7610 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
7611 DBUG_EXECUTE_IF("get_source_server_id.ER_NET_READ_INTERRUPTED", {
2677 DBUG_SET("+d,inject_ER_NET_READ_INTERRUPTED");
2678 DBUG_SET(
2679 "-d,get_source_server_id."
2680 "ER_NET_READ_INTERRUPTED");
2681 });
2682
1/2
✓ Branch 0 taken 7611 times.
✗ Branch 1 not taken.
7611 if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT @@GLOBAL.SERVER_ID")) &&
2683
6/8
✓ Branch 0 taken 7609 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7609 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7609 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7609 times.
✓ Branch 7 taken 2 times.
15220 (master_res = mysql_store_result(mysql)) &&
2684
2/4
✓ Branch 0 taken 7609 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7609 times.
✗ Branch 3 not taken.
7609 (master_row = mysql_fetch_row(master_res))) {
2685 15218 if ((::server_id ==
2686
4/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7595 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 7601 times.
7623 (mi->master_id = strtoul(master_row[0], nullptr, 10))) &&
2687
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 !mi->rli->replicate_same_server_id) {
2688 8 errmsg =
2689 "The slave I/O thread stops because master and slave have equal "
2690 "MySQL server ids; these ids must be different for replication to "
2691 "work (or the --replicate-same-server-id option must be used on "
2692 "slave but this does not always make sense; please check the "
2693 "manual before using it).";
2694 8 err_code = ER_SLAVE_FATAL_ERROR;
2695
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 sprintf(err_buff, ER_THD(current_thd, ER_SLAVE_FATAL_ERROR), errmsg);
2696 8 goto err;
2697 }
2698
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 } else if (mysql_errno(mysql) != ER_UNKNOWN_SYSTEM_VARIABLE) {
2699
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (check_io_slave_killed(mi->info_thd, mi, nullptr))
2700 goto slave_killed_err;
2701
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 else if (is_network_error(mysql_errno(mysql))) {
2702
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2703 "Get master SERVER_ID failed with error: %s",
2704 mysql_error(mysql));
2705 2 goto network_err;
2706 }
2707 /* Fatal error */
2708 errmsg =
2709 "The slave I/O thread stops because a fatal error is encountered "
2710 "when it try to get the value of SERVER_ID variable from master.";
2711 err_code = mysql_errno(mysql);
2712 sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql));
2713 goto err;
2714 } else {
2715 mi->report(WARNING_LEVEL, ER_SERVER_UNKNOWN_SYSTEM_VARIABLE,
2716 "Unknown system variable 'SERVER_ID' on master, maybe it "
2717 "is a *VERY OLD MASTER*.");
2718 }
2719
1/2
✓ Branch 0 taken 7601 times.
✗ Branch 1 not taken.
7601 if (master_res) {
2720
1/2
✓ Branch 0 taken 7601 times.
✗ Branch 1 not taken.
7601 mysql_free_result(master_res);
2721 7601 master_res = nullptr;
2722 }
2723
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 7601 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7601 times.
7601 if (mi->master_id == 0 && mi->ignore_server_ids->dynamic_ids.size() > 0) {
2724 errmsg =
2725 "Slave configured with server id filtering could not detect the master "
2726 "server id.";
2727 err_code = ER_SLAVE_FATAL_ERROR;
2728 sprintf(err_buff, ER_THD(current_thd, ER_SLAVE_FATAL_ERROR), errmsg);
2729 goto err;
2730 }
2731
2732
2/2
✓ Branch 0 taken 7600 times.
✓ Branch 1 taken 1 times.
7601 if (mi->heartbeat_period != 0.0) {
2733 char llbuf[22];
2734 7600 const char query_format[] =
2735 "SET @master_heartbeat_period = %s, @source_heartbeat_period = %s";
2736 char query[sizeof(query_format) - 2 * 2 + 2 * sizeof(llbuf) + 1];
2737 /*
2738 the period is an ulonglong of nano-secs.
2739 */
2740
1/2
✓ Branch 0 taken 7600 times.
✗ Branch 1 not taken.
7600 llstr((ulonglong)(mi->heartbeat_period * 1000000000UL), llbuf);
2741 7600 sprintf(query, query_format, llbuf, llbuf);
2742
2743
5/8
✓ Branch 0 taken 7600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7597 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
7600 DBUG_EXECUTE_IF("get_master_version.heartbeat.ER_NET_READ_INTERRUPTED", {
2744 DBUG_SET("+d,inject_ER_NET_READ_INTERRUPTED");
2745 DBUG_SET(
2746 "-d,get_master_version.heartbeat."
2747 "ER_NET_READ_INTERRUPTED");
2748 });
2749
2750
3/4
✓ Branch 0 taken 7600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7597 times.
7600 if (mysql_real_query(mysql, query, static_cast<ulong>(strlen(query)))) {
2751
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (check_io_slave_killed(mi->info_thd, mi, nullptr))
2752 goto slave_killed_err;
2753
2754
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 if (is_network_error(mysql_errno(mysql))) {
2755
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mi->report(
2756
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 WARNING_LEVEL, mysql_errno(mysql),
2757 "SET @master_heartbeat_period to master failed with error: %s",
2758 mysql_error(mysql));
2759
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 mysql_free_result(mysql_store_result(mysql));
2760 3 goto network_err;
2761 } else {
2762 /* Fatal error */
2763 errmsg =
2764 "The slave I/O thread stops because a fatal error is encountered "
2765 " when it tries to SET @master_heartbeat_period on master.";
2766 err_code = ER_SLAVE_FATAL_ERROR;
2767 sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql));
2768 mysql_free_result(mysql_store_result(mysql));
2769 goto err;
2770 }
2771 }
2772
2/4
✓ Branch 0 taken 7597 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7597 times.
✗ Branch 3 not taken.
7597 mysql_free_result(mysql_store_result(mysql));
2773 }
2774
2775 /*
2776 Querying if master is capable to checksum and notifying it about own
2777 CRC-awareness. The master's side instant value of @@global.binlog_checksum
2778 is stored in the dump thread's uservar area as well as cached locally
2779 to become known in consensus by master and slave.
2780 */
2781
3/4
✓ Branch 0 taken 7598 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7597 times.
✓ Branch 3 taken 1 times.
7598 if (DBUG_EVALUATE_IF("simulate_replica_unaware_checksum", 0, 1)) {
2782 int rc;
2783 // Set both variables, so that it works equally on both old and new
2784 // source server.
2785 7597 const char query[] =
2786 "SET @master_binlog_checksum = @@global.binlog_checksum, "
2787 "@source_binlog_checksum = @@global.binlog_checksum";
2788 7597 master_res = nullptr;
2789 // initially undefined
2790 7597 mi->checksum_alg_before_fd = binary_log::BINLOG_CHECKSUM_ALG_UNDEF;
2791 /*
2792 @c checksum_alg_before_fd is queried from master in this block.
2793 If master is old checksum-unaware the value stays undefined.
2794 Once the first FD will be received its alg descriptor will replace
2795 the being queried one.
2796 */
2797
1/2
✓ Branch 0 taken 7597 times.
✗ Branch 1 not taken.
7597 rc = mysql_real_query(mysql, query, static_cast<ulong>(strlen(query)));
2798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7597 times.
7597 if (rc != 0) {
2799 mi->checksum_alg_before_fd = binary_log::BINLOG_CHECKSUM_ALG_OFF;
2800 if (check_io_slave_killed(mi->info_thd, mi, nullptr))
2801 1 goto slave_killed_err;
2802
2803 if (mysql_errno(mysql) == ER_UNKNOWN_SYSTEM_VARIABLE) {
2804 // this is tolerable as OM -> NS is supported
2805 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2806 "Notifying master by %s failed with "
2807 "error: %s",
2808 query, mysql_error(mysql));
2809 } else {
2810 if (is_network_error(mysql_errno(mysql))) {
2811 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2812 "Notifying master by %s failed with "
2813 "error: %s",
2814 query, mysql_error(mysql));
2815 mysql_free_result(mysql_store_result(mysql));
2816 goto network_err;
2817 } else {
2818 errmsg =
2819 "The slave I/O thread stops because a fatal error is encountered "
2820 "when it tried to SET @master_binlog_checksum on master.";
2821 err_code = ER_SLAVE_FATAL_ERROR;
2822 sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql));
2823 mysql_free_result(mysql_store_result(mysql));
2824 3 goto err;
2825 }
2826 }
2827 } else {
2828
2/4
✓ Branch 0 taken 7597 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7597 times.
✗ Branch 3 not taken.
7597 mysql_free_result(mysql_store_result(mysql));
2829 // Read back the user variable that we just set, to verify that
2830 // the source recognized the checksum algorithm.
2831
1/2
✓ Branch 0 taken 7597 times.
✗ Branch 1 not taken.
7597 if (!mysql_real_query(
2832 7596 mysql, STRING_WITH_LEN("SELECT @source_binlog_checksum")) &&
2833
2/4
✓ Branch 0 taken 7596 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7596 times.
✗ Branch 3 not taken.
7596 (master_res = mysql_store_result(mysql)) &&
2834
6/8
✓ Branch 0 taken 7596 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 7596 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7596 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7596 times.
✓ Branch 7 taken 1 times.
22789 (master_row = mysql_fetch_row(master_res)) &&
2835
1/2
✓ Branch 0 taken 7596 times.
✗ Branch 1 not taken.
7596 (master_row[0] != nullptr)) {
2836 7596 mi->checksum_alg_before_fd = static_cast<enum_binlog_checksum_alg>(
2837
1/2
✓ Branch 0 taken 7596 times.
✗ Branch 1 not taken.
7596 find_type(master_row[0], &binlog_checksum_typelib, 1) - 1);
2838
2839
3/4
✓ Branch 0 taken 7596 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7593 times.
7596 DBUG_EXECUTE_IF("undefined_algorithm_on_replica",
2840 mi->checksum_alg_before_fd =
2841 binary_log::BINLOG_CHECKSUM_ALG_UNDEF;);
2842
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7593 times.
7596 if (mi->checksum_alg_before_fd ==
2843 binary_log::BINLOG_CHECKSUM_ALG_UNDEF) {
2844 3 errmsg =
2845 "The slave I/O thread was stopped because a fatal error is "
2846 "encountered "
2847 "The checksum algorithm used by master is unknown to slave.";
2848 3 err_code = ER_SLAVE_FATAL_ERROR;
2849
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql));
2850
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 mysql_free_result(mysql_store_result(mysql));
2851 3 goto err;
2852 }
2853
2854 // valid outcome is either of
2855
3/4
✓ Branch 0 taken 7583 times.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7583 times.
7593 assert(mi->checksum_alg_before_fd ==
2856 binary_log::BINLOG_CHECKSUM_ALG_OFF ||
2857 mi->checksum_alg_before_fd ==
2858 binary_log::BINLOG_CHECKSUM_ALG_CRC32);
2859
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 } else if (check_io_slave_killed(mi->info_thd, mi, nullptr))
2860 1 goto slave_killed_err;
2861 else if (is_network_error(mysql_errno(mysql))) {
2862 mi->report(WARNING_LEVEL, mysql_errno(mysql),
2863 "Get master BINLOG_CHECKSUM failed with error: %s",
2864 mysql_error(mysql));
2865 goto network_err;
2866 } else {
2867 errmsg =
2868 "The slave I/O thread stops because a fatal error is encountered "
2869 "when it tried to SELECT @master_binlog_checksum.";
2870 err_code = ER_SLAVE_FATAL_ERROR;
2871 sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql));
2872 mysql_free_result(mysql_store_result(mysql));
2873 goto err;
2874 }
2875 }
2876
1/2
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
7593 if (master_res) {
2877
1/2
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
7593 mysql_free_result(master_res);
2878 7593 master_res = nullptr;
2879 }
2880 } else
2881 1 mi->checksum_alg_before_fd = binary_log::BINLOG_CHECKSUM_ALG_OFF;
2882
2883
2/4
✓ Branch 0 taken 7594 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7594 times.
7594 if (DBUG_EVALUATE_IF("bug32442749_simulate_null_checksum", 1, 0)) {
2884 const char query[] = "SET @source_binlog_checksum= NULL";
2885 int rc = mysql_real_query(mysql, query, static_cast<ulong>(strlen(query)));
2886 if (rc != 0) {
2887 errmsg =
2888 "The slave I/O thread stops because a fatal error is encountered "
2889 "when it tried to SET @source_binlog_checksum.";
2890 err_code = ER_SLAVE_FATAL_ERROR;
2891 sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql));
2892 mysql_free_result(mysql_store_result(mysql));
2893 goto err;
2894 }
2895 mysql_free_result(mysql_store_result(mysql));
2896 }
2897
2898
2/4
✓ Branch 0 taken 7594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7594 times.
✗ Branch 3 not taken.
7594 if (DBUG_EVALUATE_IF("simulate_replica_unaware_gtid", 0, 1)) {
2899 7594 auto master_gtid_mode = Gtid_mode::OFF;
2900
1/2
✓ Branch 0 taken 7594 times.
✗ Branch 1 not taken.
7594 auto slave_gtid_mode = global_gtid_mode.get();
2901
3/6
✓ Branch 0 taken 7594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7593 times.
✗ Branch 5 not taken.
7594 switch (io_thread_init_command(mi, "SELECT @@GLOBAL.GTID_MODE",
2902 ER_UNKNOWN_SYSTEM_VARIABLE, &master_res,
2903 &master_row)) {
2904 1 case COMMAND_STATUS_ERROR:
2905 44 return 2;
2906 case COMMAND_STATUS_ALLOWED_ERROR:
2907 // master is old and does not have @@GLOBAL.GTID_MODE
2908 master_gtid_mode = Gtid_mode::OFF;
2909 break;
2910 7593 case COMMAND_STATUS_OK: {
2911 7593 const char *master_gtid_mode_string = master_row[0];
2912
2/4
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7593 times.
7593 DBUG_EXECUTE_IF("simulate_source_has_gtid_mode_on_something",
2913 { master_gtid_mode_string = "on_something"; });
2914
2/4
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7593 times.
7593 DBUG_EXECUTE_IF("simulate_source_has_gtid_mode_off_something",
2915 { master_gtid_mode_string = "off_something"; });
2916
3/4
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7590 times.
7593 DBUG_EXECUTE_IF("simulate_source_has_unknown_gtid_mode",
2917 { master_gtid_mode_string = "Krakel Spektakel"; });
2918 bool error;
2919 7593 std::tie(error, master_gtid_mode) =
2920
2/4
✓ Branch 0 taken 7593 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7593 times.
✗ Branch 3 not taken.
15186 Gtid_mode::from_string(master_gtid_mode_string);
2921
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7590 times.
7593 if (error) {
2922
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
2923 "The slave IO thread stops because the master has "
2924 "an unknown @@GLOBAL.GTID_MODE '%s'.",
2925 master_gtid_mode_string);
2926
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mysql_free_result(master_res);
2927 3 return 1;
2928 }
2929
1/2
✓ Branch 0 taken 7590 times.
✗ Branch 1 not taken.
7590 mysql_free_result(master_res);
2930 7590 break;
2931 }
2932 }
2933 12614 if ((slave_gtid_mode == Gtid_mode::OFF &&
2934
8/8
✓ Branch 0 taken 5024 times.
✓ Branch 1 taken 2566 times.
✓ Branch 2 taken 5018 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 2515 times.
✓ Branch 5 taken 5069 times.
✓ Branch 6 taken 19 times.
✓ Branch 7 taken 7571 times.
10105 master_gtid_mode >= Gtid_mode::ON_PERMISSIVE) ||
2935 2515 (slave_gtid_mode == Gtid_mode::ON &&
2936
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2483 times.
2515 master_gtid_mode <= Gtid_mode::OFF_PERMISSIVE &&
2937
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 19 times.
32 mi->rli->m_assign_gtids_to_anonymous_transactions_info.get_type() ==
2938 Assign_gtids_to_anonymous_transactions_info::enum_type::
2939 AGAT_OFF)) {
2940
3/6
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
19 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
2941 "The replication receiver thread cannot start because "
2942 "the master has GTID_MODE = %.192s and this server has "
2943 "GTID_MODE = %.192s.",
2944 Gtid_mode::to_string(master_gtid_mode),
2945 Gtid_mode::to_string(slave_gtid_mode));
2946 19 return 1;
2947 }
2948
6/6
✓ Branch 0 taken 2316 times.
✓ Branch 1 taken 5255 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 2295 times.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 7550 times.
7571 if (mi->is_auto_position() && master_gtid_mode != Gtid_mode::ON) {
2949
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
2950 "The replication receiver thread cannot start in "
2951 "AUTO_POSITION mode: the master has GTID_MODE = %.192s "
2952 "instead of ON.",
2953 Gtid_mode::to_string(master_gtid_mode));
2954 21 return 1;
2955 }
2956 }
2957
2958 err:
2959
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7550 times.
7561 if (errmsg) {
2960
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 if (master_res) mysql_free_result(master_res);
2961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 assert(err_code != 0);
2962
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 mi->report(ERROR_LEVEL, err_code, "%s", err_buff);
2963 11 return 1;
2964 }
2965
2966 7550 return 0;
2967
2968 7 network_err:
2969
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 if (master_res) mysql_free_result(master_res);
2970 7 mi->set_network_error();
2971 7 return 2;
2972
2973 2 slave_killed_err:
2974
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (master_res) mysql_free_result(master_res);
2975 2 return 2;
2976 7614 }
2977
2978 77 static bool wait_for_relay_log_space(Relay_log_info *rli) {
2979 77 bool slave_killed = false;
2980 77 Master_info *mi = rli->mi;
2981 77 PSI_stage_info old_stage;
2982 77 THD *thd = mi->info_thd;
2983
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 DBUG_TRACE;
2984
2985
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 mysql_mutex_lock(&rli->log_space_lock);
2986
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 thd->ENTER_COND(&rli->log_space_cond, &rli->log_space_lock,
2987 &stage_waiting_for_relay_log_space, &old_stage);
2988 77 while (rli->log_space_limit < rli->log_space_total &&
2989
7/8
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 169 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 166 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 95 times.
✓ Branch 7 taken 77 times.
338 !(slave_killed = io_slave_killed(thd, mi)) &&
2990
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 71 times.
166 !rli->ignore_log_space_limit)
2991
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 mysql_cond_wait(&rli->log_space_cond, &rli->log_space_lock);
2992
2993 /*
2994 Makes the IO thread read only one event at a time
2995 until the SQL thread is able to purge the relay
2996 logs, freeing some space.
2997
2998 Therefore, once the SQL thread processes this next
2999 event, it goes to sleep (no more events in the queue),
3000 sets ignore_log_space_limit=true and wakes the IO thread.
3001 However, this event may have been enough already for
3002 the SQL thread to purge some log files, freeing
3003 rli->log_space_total .
3004
3005 This guarantees that the SQL and IO thread move
3006 forward only one event at a time (to avoid deadlocks),
3007 when the relay space limit is reached. It also
3008 guarantees that when the SQL thread is prepared to
3009 rotate (to be able to purge some logs), the IO thread
3010 will know about it and will rotate.
3011
3012 NOTE: The ignore_log_space_limit is only set when the SQL
3013 thread sleeps waiting for events.
3014
3015 */
3016
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 6 times.
77 if (rli->ignore_log_space_limit) {
3017 #ifndef NDEBUG
3018 {
3019 char llbuf1[22], llbuf2[22];
3020
3/12
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 71 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
71 DBUG_PRINT("info", ("log_space_limit=%s "
3021 "log_space_total=%s "
3022 "ignore_log_space_limit=%d "
3023 "sql_force_rotate_relay=%d",
3024 llstr(rli->log_space_limit, llbuf1),
3025 llstr(rli->log_space_total, llbuf2),
3026 (int)rli->ignore_log_space_limit,
3027 (int)rli->sql_force_rotate_relay));
3028 }
3029 #endif
3030
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 39 times.
71 if (rli->sql_force_rotate_relay) {
3031
4/6
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
32 DBUG_EXECUTE_IF("rpl_before_forced_rotate", {
3032 rpl_replica_debug_point(DBUG_RPL_S_BEFORE_FORCED_ROTATE);
3033 });
3034
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 rotate_relay_log(mi, true, true, false);
3035 32 rli->sql_force_rotate_relay = false;
3036 }
3037
3038 71 rli->ignore_log_space_limit = false;
3039 }
3040
3041
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 mysql_mutex_unlock(&rli->log_space_lock);
3042
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 thd->EXIT_COND(&old_stage);
3043 77 return slave_killed;
3044 77 }
3045
3046 /*
3047 Builds a Rotate and writes it to relay log.
3048
3049 The caller must hold mi->data_lock.
3050
3051 @param thd pointer to I/O Thread's Thd.
3052 @param mi point to I/O Thread metadata class.
3053 @param force_flush_mi_info when true, do not respect sync period and flush
3054 information.
3055 when false, flush will only happen if it is time to
3056 flush.
3057
3058 @return 0 if everything went fine, 1 otherwise.
3059 */
3060 12077 static int write_rotate_to_master_pos_into_relay_log(THD *thd, Master_info *mi,
3061 bool force_flush_mi_info) {
3062 12077 Relay_log_info *rli = mi->rli;
3063 12077 int error = 0;
3064
1/2
✓ Branch 0 taken 12077 times.
✗ Branch 1 not taken.
12077 DBUG_TRACE;
3065
3066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12077 times.
12077 assert(thd == mi->info_thd);
3067 12077 mysql_mutex_assert_owner(rli->relay_log.get_log_lock());
3068
3069
3/8
✓ Branch 0 taken 12077 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12077 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12077 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
12077 DBUG_PRINT("info", ("writing a Rotate event to the relay log"));
3070 12077 Rotate_log_event *ev = new Rotate_log_event(mi->get_master_log_name(), 0,
3071 12077 mi->get_master_log_pos(),
3072
2/4
✓ Branch 0 taken 12077 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12077 times.
✗ Branch 3 not taken.
12077 Rotate_log_event::DUP_NAME);
3073
3074
5/8
✓ Branch 0 taken 12077 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12076 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
12077 DBUG_EXECUTE_IF("fail_generating_rotate_event_on_write_rotate_to_source_pos",
3075 {
3076 if (likely((bool)ev)) {
3077 delete ev;
3078 ev = nullptr;
3079 }
3080 });
3081
3082
2/2
✓ Branch 0 taken 12076 times.
✓ Branch 1 taken 1 times.
12077 if (likely((bool)ev)) {
3083
1/2
✓ Branch 0 taken 12076 times.
✗ Branch 1 not taken.
12076 if (mi->get_mi_description_event() != nullptr)
3084 12076 ev->common_footer->checksum_alg =
3085 12076 mi->get_mi_description_event()->common_footer->checksum_alg;
3086
3087 12076 ev->server_id = 0; // don't be ignored by slave SQL thread
3088
4/6
✓ Branch 0 taken 12076 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12076 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 12075 times.
12076 if (unlikely(rli->relay_log.write_event(ev, mi) != 0))
3089
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE,
3090 ER_THD(thd, ER_SLAVE_RELAY_LOG_WRITE_FAILURE),
3091 "failed to write a Rotate event"
3092 " to the relay log, SHOW SLAVE STATUS may be"
3093 " inaccurate");
3094
1/2
✓ Branch 0 taken 12076 times.
✗ Branch 1 not taken.
12076 mysql_mutex_lock(&mi->data_lock);
3095
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12075 times.
12076 if (flush_master_info(mi, force_flush_mi_info, false, false,
3096
2/4
✓ Branch 0 taken 12076 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12076 times.
✗ Branch 3 not taken.
12076 mi->is_gtid_only_mode())) {
3097 1 error = 1;
3098
8/16
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
1 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_CANT_FLUSH_MASTER_INFO_FILE);
3099 }
3100
1/2
✓ Branch 0 taken 12076 times.
✗ Branch 1 not taken.
12076 mysql_mutex_unlock(&mi->data_lock);
3101
1/2
✓ Branch 0 taken 12076 times.
✗ Branch 1 not taken.
12076 delete ev;
3102 } else {
3103 1 error = 1;
3104
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 mi->report(ERROR_LEVEL, ER_SLAVE_CREATE_EVENT_FAILURE,
3105 ER_THD(thd, ER_SLAVE_CREATE_EVENT_FAILURE),
3106 "Rotate_event (out of memory?),"
3107 " SHOW SLAVE STATUS may be inaccurate");
3108 }
3109
3110 12077 return error;
3111 12077 }
3112
3113 /*
3114 Builds a Rotate from the ignored events' info and writes it to relay log.
3115
3116 @param thd pointer to I/O Thread's Thd.
3117 @param mi point to I/O Thread metadata class.
3118
3119 @return 0 if everything went fine, 1 otherwise.
3120 */
3121 7265 static int write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi) {
3122 7265 Relay_log_info *rli = mi->rli;
3123 7265 mysql_mutex_t *end_pos_lock = rli->relay_log.get_binlog_end_pos_lock();
3124 7265 int error = 0;
3125
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 DBUG_TRACE;
3126
3127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7265 times.
7265 assert(thd == mi->info_thd);
3128
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mysql_mutex_lock(rli->relay_log.get_log_lock());
3129
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mysql_mutex_lock(end_pos_lock);
3130
3131
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7261 times.
7265 if (rli->ign_master_log_name_end[0]) {
3132
3/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4 DBUG_PRINT("info", ("writing a Rotate event to track down ignored events"));
3133 /*
3134 If the ignored events' info still hold, they should have same info as
3135 the mi->get_master_log_[name|pos].
3136 */
3137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(strcmp(rli->ign_master_log_name_end, mi->get_master_log_name()) ==
3138 0);
3139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(rli->ign_master_log_pos_end == mi->get_master_log_pos());
3140
3141 /* Avoid the applier to get the ignored event' info by rli->ign* */
3142 4 rli->ign_master_log_name_end[0] = 0;
3143 /* can unlock before writing as the relay log will soon have our Rotate */
3144
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 mysql_mutex_unlock(end_pos_lock);
3145
3146 /* Generate the rotate based on mi position */
3147
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 error = write_rotate_to_master_pos_into_relay_log(
3148 thd, mi, false /* force_flush_mi_info */);
3149 } else
3150
1/2
✓ Branch 0 taken 7261 times.
✗ Branch 1 not taken.
7261 mysql_mutex_unlock(end_pos_lock);
3151
3152
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mysql_mutex_unlock(rli->relay_log.get_log_lock());
3153 7265 return error;
3154 7265 }
3155
3156 7509 static int register_slave_on_master(MYSQL *mysql, Master_info *mi,
3157 bool *suppress_warnings) {
3158 7509 uchar buf[1024], *pos = buf;
3159 7509 size_t report_host_len = 0, report_user_len = 0, report_password_len = 0;
3160
1/2
✓ Branch 0 taken 7509 times.
✗ Branch 1 not taken.
7509 DBUG_TRACE;
3161
3162 7509 *suppress_warnings = false;
3163
2/2
✓ Branch 0 taken 6924 times.
✓ Branch 1 taken 585 times.
7509 if (report_host) report_host_len = strlen(report_host);
3164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7509 times.
7509 if (report_host_len > HOSTNAME_LENGTH) {
3165 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_REPORT_HOST_TOO_LONG, report_host_len,
3166 HOSTNAME_LENGTH, mi->get_for_channel_str());
3167 return 0;
3168 }
3169
3170
2/2
✓ Branch 0 taken 6921 times.
✓ Branch 1 taken 588 times.
7509 if (report_user) report_user_len = strlen(report_user);
3171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7509 times.
7509 if (report_user_len > USERNAME_LENGTH) {
3172 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_REPORT_USER_TOO_LONG, report_user_len,
3173 USERNAME_LENGTH, mi->get_for_channel_str());
3174 return 0;
3175 }
3176
3177
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7502 times.
7509 if (report_password) report_password_len = strlen(report_password);
3178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7509 times.
7509 if (report_password_len > MAX_PASSWORD_LENGTH) {
3179 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_REPORT_PASSWORD_TOO_LONG,
3180 report_password_len, MAX_PASSWORD_LENGTH, mi->get_for_channel_str());
3181 return 0;
3182 }
3183
3184 7509 int4store(pos, server_id);
3185 7509 pos += 4;
3186
1/2
✓ Branch 0 taken 7509 times.
✗ Branch 1 not taken.
7509 pos = net_store_data(pos, (uchar *)report_host, report_host_len);
3187
1/2
✓ Branch 0 taken 7509 times.
✗ Branch 1 not taken.
7509 pos = net_store_data(pos, (uchar *)report_user, report_user_len);
3188
1/2
✓ Branch 0 taken 7509 times.
✗ Branch 1 not taken.
7509 pos = net_store_data(pos, (uchar *)report_password, report_password_len);
3189 7509 int2store(pos, (uint16)report_port);
3190 7509 pos += 2;
3191 /*
3192 Fake rpl_recovery_rank, which was removed in BUG#13963,
3193 so that this server can register itself on old servers,
3194 see BUG#49259.
3195 */
3196 7509 int4store(pos, /* rpl_recovery_rank */ 0);
3197 7509 pos += 4;
3198 /* The master will fill in master_id */
3199 7509 int4store(pos, 0);
3200 7509 pos += 4;
3201
3202
4/8
✓ Branch 0 taken 7509 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7509 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 74 times.
✓ Branch 7 taken 7435 times.
7509 if (simple_command(mysql, COM_REGISTER_SLAVE, buf, (size_t)(pos - buf), 0)) {
3203
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 uint err{mysql_errno(mysql)};
3204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 if (err == ER_NET_READ_INTERRUPTED) {
3205 *suppress_warnings = true; // Suppress reconnect warning
3206
2/4
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74 times.
✗ Branch 3 not taken.
74 } else if (!check_io_slave_killed(mi->info_thd, mi, nullptr)) {
3207
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 std::stringstream ss;
3208
5/10
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 74 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 74 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 74 times.
✗ Branch 9 not taken.
74 ss << mysql_error(mysql) << " (Errno: " << err << ")";
3209
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
148 mi->report(ERROR_LEVEL, ER_SLAVE_MASTER_COM_FAILURE,
3210
2/4
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74 times.
✗ Branch 3 not taken.
74 ER_THD(current_thd, ER_SLAVE_MASTER_COM_FAILURE),
3211
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
148 "COM_REGISTER_SLAVE", ss.str().c_str());
3212 74 }
3213
2/4
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 74 times.
74 if (is_network_error(err)) mi->set_network_error();
3214 74 return 1;
3215 }
3216
3217
3/4
✓ Branch 0 taken 7435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7434 times.
7435 DBUG_EXECUTE_IF("simulate_register_replica_killed", {
3218 mi->abort_slave = 1;
3219 return 1;
3220 };);
3221 7434 return 0;
3222 7509 }
3223
3224 /**
3225 Function that fills the metadata required for SHOW REPLICA STATUS.
3226 This function shall be used in two cases:
3227 1) SHOW REPLICA STATUS FOR ALL CHANNELS
3228 2) SHOW REPLICA STATUS for a channel
3229
3230 @param[in,out] field_list field_list to fill the metadata
3231 @param[in] io_gtid_set_size the size to be allocated to store
3232 the retrieved gtid set
3233 @param[in] sql_gtid_set_size the size to be allocated to store
3234 the executed gtid set
3235
3236 @todo return a bool after adding catching the exceptions to the
3237 push_back() methods for field_list.
3238 */
3239
3240 195995 static void show_slave_status_metadata(mem_root_deque<Item *> *field_list,
3241 int io_gtid_set_size,
3242 int sql_gtid_set_size) {
3243
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Replica_IO_State", 14));
3244 391990 field_list->push_back(
3245
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Source_Host", HOSTNAME_LENGTH + 1));
3246 391990 field_list->push_back(
3247
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Source_User", USERNAME_LENGTH + 1));
3248
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_return_int("Source_Port", 7, MYSQL_TYPE_LONG));
3249 391990 field_list->push_back(
3250
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Connect_Retry", 10, MYSQL_TYPE_LONG));
3251
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Source_Log_File", FN_REFLEN));
3252 391990 field_list->push_back(
3253
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Read_Source_Log_Pos", 10, MYSQL_TYPE_LONGLONG));
3254
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Relay_Log_File", FN_REFLEN));
3255 391990 field_list->push_back(
3256
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Relay_Log_Pos", 10, MYSQL_TYPE_LONGLONG));
3257 391990 field_list->push_back(
3258
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Relay_Source_Log_File", FN_REFLEN));
3259
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Replica_IO_Running", 3));
3260
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Replica_SQL_Running", 3));
3261
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Replicate_Do_DB", 20));
3262
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Replicate_Ignore_DB", 20));
3263
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Replicate_Do_Table", 20));
3264
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Replicate_Ignore_Table", 23));
3265
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Replicate_Wild_Do_Table", 24));
3266 391990 field_list->push_back(
3267
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Replicate_Wild_Ignore_Table", 28));
3268
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_return_int("Last_Errno", 4, MYSQL_TYPE_LONG));
3269
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Last_Error", 20));
3270 391990 field_list->push_back(
3271
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Skip_Counter", 10, MYSQL_TYPE_LONG));
3272 391990 field_list->push_back(
3273
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Exec_Source_Log_Pos", 10, MYSQL_TYPE_LONGLONG));
3274 391990 field_list->push_back(
3275
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Relay_Log_Space", 10, MYSQL_TYPE_LONGLONG));
3276
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Until_Condition", 6));
3277
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Until_Log_File", FN_REFLEN));
3278 391990 field_list->push_back(
3279
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Until_Log_Pos", 10, MYSQL_TYPE_LONGLONG));
3280
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Source_SSL_Allowed", 7));
3281
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Source_SSL_CA_File", FN_REFLEN));
3282
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Source_SSL_CA_Path", FN_REFLEN));
3283
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Source_SSL_Cert", FN_REFLEN));
3284
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Source_SSL_Cipher", FN_REFLEN));
3285
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Source_SSL_Key", FN_REFLEN));
3286 391990 field_list->push_back(
3287
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Seconds_Behind_Source", 10, MYSQL_TYPE_LONGLONG));
3288 391990 field_list->push_back(
3289
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Source_SSL_Verify_Server_Cert", 3));
3290 391990 field_list->push_back(
3291
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Last_IO_Errno", 4, MYSQL_TYPE_LONG));
3292
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Last_IO_Error", 20));
3293 391990 field_list->push_back(
3294
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Last_SQL_Errno", 4, MYSQL_TYPE_LONG));
3295
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Last_SQL_Error", 20));
3296 391990 field_list->push_back(
3297
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Replicate_Ignore_Server_Ids", FN_REFLEN));
3298 391990 field_list->push_back(
3299
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Source_Server_Id", sizeof(ulong), MYSQL_TYPE_LONG));
3300
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Source_UUID", UUID_LENGTH));
3301 391990 field_list->push_back(
3302
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Source_Info_File", 2 * FN_REFLEN));
3303
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_return_int("SQL_Delay", 10, MYSQL_TYPE_LONG));
3304 391990 field_list->push_back(
3305
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("SQL_Remaining_Delay", 8, MYSQL_TYPE_LONG));
3306
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Replica_SQL_Running_State", 20));
3307 391990 field_list->push_back(
3308
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Source_Retry_Count", 10, MYSQL_TYPE_LONGLONG));
3309 391990 field_list->push_back(
3310
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Source_Bind", HOSTNAME_LENGTH + 1));
3311
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Last_IO_Error_Timestamp", 20));
3312
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Last_SQL_Error_Timestamp", 20));
3313
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Source_SSL_Crl", FN_REFLEN));
3314
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Source_SSL_Crlpath", FN_REFLEN));
3315 391990 field_list->push_back(
3316
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Retrieved_Gtid_Set", io_gtid_set_size));
3317 391990 field_list->push_back(
3318
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Executed_Gtid_Set", sql_gtid_set_size));
3319 391990 field_list->push_back(
3320
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_return_int("Auto_Position", sizeof(ulong), MYSQL_TYPE_LONG));
3321
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Replicate_Rewrite_DB", 24));
3322 391990 field_list->push_back(
3323
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Channel_Name", CHANNEL_NAME_LENGTH));
3324
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 field_list->push_back(new Item_empty_string("Source_TLS_Version", FN_REFLEN));
3325 391990 field_list->push_back(
3326
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Source_public_key_path", FN_REFLEN));
3327
2/4
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
391990 field_list->push_back(new Item_return_int("Get_Source_public_key",
3328
1/2
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
391990 sizeof(ulong), MYSQL_TYPE_LONG));
3329 391990 field_list->push_back(
3330
3/6
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195995 times.
✗ Branch 5 not taken.
195995 new Item_empty_string("Network_Namespace", NAME_LEN + 1));
3331 195995 }
3332
3333 /**
3334 Send the data to the client of a Master_info during show_slave_status()
3335 This function has to be called after calling show_slave_status_metadata().
3336 Just before sending the data, thd->get_protocol() is prepared to (re)send;
3337
3338 @param[in] thd client thread
3339 @param[in] mi the master info. In the case of multisource
3340 replication, this master info corresponds to a
3341 channel.
3342
3343 @param[in] io_gtid_set_buffer buffer related to Retrieved GTID set
3344 for each channel.
3345 @param[in] sql_gtid_set_buffer buffer related to Executed GTID set
3346 for each channel.
3347 @retval 0 success
3348 @retval 1 Error
3349 */
3350
3351 168272 static bool show_slave_status_send_data(THD *thd, Master_info *mi,
3352 char *io_gtid_set_buffer,
3353 char *sql_gtid_set_buffer) {
3354
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 DBUG_TRACE;
3355
3356 168272 Protocol *protocol = thd->get_protocol();
3357 168272 char *slave_sql_running_state = nullptr;
3358 168272 Rpl_filter *rpl_filter = mi->rli->rpl_filter;
3359
3360
3/8
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 168272 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
168272 DBUG_PRINT("info", ("host is set: '%s'", mi->host));
3361
3362
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->start_row();
3363
3364 /*
3365 slave_running can be accessed without run_lock but not other
3366 non-volatile members like mi->info_thd or rli->info_thd, for
3367 them either info_thd_lock or run_lock hold is required.
3368 */
3369
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 mysql_mutex_lock(&mi->info_thd_lock);
3370
4/6
✓ Branch 0 taken 115786 times.
✓ Branch 1 taken 52486 times.
✓ Branch 2 taken 115786 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 168272 times.
✗ Branch 5 not taken.
168272 protocol->store(mi->info_thd ? mi->info_thd->proc_info_session(thd) : "",
3371 &my_charset_bin);
3372
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 mysql_mutex_unlock(&mi->info_thd_lock);
3373
3374
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 mysql_mutex_lock(&mi->rli->info_thd_lock);
3375 58147 slave_sql_running_state = const_cast<char *>(
3376
3/4
✓ Branch 0 taken 110125 times.
✓ Branch 1 taken 58147 times.
✓ Branch 2 taken 110125 times.
✗ Branch 3 not taken.
168272 mi->rli->info_thd ? mi->rli->info_thd->proc_info_session(thd) : "");
3377
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 mysql_mutex_unlock(&mi->rli->info_thd_lock);
3378
3379
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 mysql_mutex_lock(&mi->data_lock);
3380
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 mysql_mutex_lock(&mi->rli->data_lock);
3381
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 mysql_mutex_lock(&mi->err_lock);
3382
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 mysql_mutex_lock(&mi->rli->err_lock);
3383
3384
2/4
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
168272 DEBUG_SYNC(thd, "wait_after_lock_active_mi_and_rli_data_lock_is_acquired");
3385
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->host, &my_charset_bin);
3386
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->get_user(), &my_charset_bin);
3387
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store((uint32)mi->port);
3388
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store((uint32)mi->connect_retry);
3389
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->get_master_log_name_info(), &my_charset_bin);
3390
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store((ulonglong)mi->get_master_log_pos_info());
3391 168272 protocol->store(mi->rli->get_group_relay_log_name() +
3392
2/4
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
168272 dirname_length(mi->rli->get_group_relay_log_name()),
3393 &my_charset_bin);
3394
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store((ulonglong)mi->rli->get_group_relay_log_pos());
3395
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->rli->get_group_master_log_name_info(), &my_charset_bin);
3396
3/4
✓ Branch 0 taken 53950 times.
✓ Branch 1 taken 114322 times.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
222222 protocol->store(
3397 168272 mi->slave_running == MYSQL_SLAVE_RUN_CONNECT
3398 ? "Yes"
3399
2/2
✓ Branch 0 taken 1464 times.
✓ Branch 1 taken 52486 times.
53950 : (mi->slave_running == MYSQL_SLAVE_RUN_NOT_CONNECT ? "Connecting"
3400 : "No"),
3401 &my_charset_bin);
3402
3/4
✓ Branch 0 taken 110119 times.
✓ Branch 1 taken 58153 times.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
168272 protocol->store(mi->rli->slave_running ? "Yes" : "No", &my_charset_bin);
3403
3404 /*
3405 Acquire the read lock, because the filter may be modified by
3406 CHANGE REPLICATION FILTER when slave is not running.
3407 */
3408
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 rpl_filter->rdlock();
3409
2/4
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
168272 store(protocol, rpl_filter->get_do_db());
3410
2/4
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
168272 store(protocol, rpl_filter->get_ignore_db());
3411
3412 char buf[256];
3413 168272 String tmp(buf, sizeof(buf), &my_charset_bin);
3414
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 rpl_filter->get_do_table(&tmp);
3415
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(&tmp);
3416
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 rpl_filter->get_ignore_table(&tmp);
3417
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(&tmp);
3418
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 rpl_filter->get_wild_do_table(&tmp);
3419
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(&tmp);
3420
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 rpl_filter->get_wild_ignore_table(&tmp);
3421
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(&tmp);
3422
3423
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->rli->last_error().number);
3424
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->rli->last_error().message, &my_charset_bin);
3425
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store((uint32)mi->rli->slave_skip_counter);
3426
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store((ulonglong)mi->rli->get_group_master_log_pos_info());
3427
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store((ulonglong)mi->rli->log_space_total);
3428
3429 168272 const char *until_type = "";
3430
3431
8/9
✓ Branch 0 taken 167467 times.
✓ Branch 1 taken 365 times.
✓ Branch 2 taken 114 times.
✓ Branch 3 taken 202 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 20 times.
✓ Branch 6 taken 21 times.
✓ Branch 7 taken 71 times.
✗ Branch 8 not taken.
168272 switch (mi->rli->until_condition) {
3432 167467 case Relay_log_info::UNTIL_NONE:
3433 167467 until_type = "None";
3434 167467 break;
3435 365 case Relay_log_info::UNTIL_MASTER_POS:
3436
2/2
✓ Branch 0 taken 364 times.
✓ Branch 1 taken 1 times.
365 if (thd->lex->is_replication_deprecated_syntax_used())
3437 364 until_type = "Master";
3438 else
3439 1 until_type = "Source";
3440 365 break;
3441 114 case Relay_log_info::UNTIL_RELAY_POS:
3442 114 until_type = "Relay";
3443 114 break;
3444 202 case Relay_log_info::UNTIL_SQL_BEFORE_GTIDS:
3445 202 until_type = "SQL_BEFORE_GTIDS";
3446 202 break;
3447 12 case Relay_log_info::UNTIL_SQL_AFTER_GTIDS:
3448 12 until_type = "SQL_AFTER_GTIDS";
3449 12 break;
3450 20 case Relay_log_info::UNTIL_SQL_VIEW_ID:
3451 20 until_type = "SQL_VIEW_ID";
3452 20 break;
3453 21 case Relay_log_info::UNTIL_SQL_AFTER_MTS_GAPS:
3454 21 until_type = "SQL_AFTER_MTS_GAPS";
3455 21 break;
3456 71 case Relay_log_info::UNTIL_DONE:
3457 71 until_type = "DONE";
3458 71 break;
3459 default:
3460 assert(0);
3461 }
3462
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(until_type, &my_charset_bin);
3463
2/4
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
168272 protocol->store(mi->rli->get_until_log_name(), &my_charset_bin);
3464
2/4
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
168272 protocol->store((ulonglong)mi->rli->get_until_log_pos());
3465
3466
3/4
✓ Branch 0 taken 1688 times.
✓ Branch 1 taken 166584 times.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
168272 protocol->store(mi->ssl ? "Yes" : "No", &my_charset_bin);
3467
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->ssl_ca, &my_charset_bin);
3468
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->ssl_capath, &my_charset_bin);
3469
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->ssl_cert, &my_charset_bin);
3470
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->ssl_cipher, &my_charset_bin);
3471
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->ssl_key, &my_charset_bin);
3472
3473 /*
3474 The pseudo code to compute Seconds_Behind_Master:
3475 if (SQL thread is running)
3476 {
3477 if (SQL thread processed all the available relay log)
3478 {
3479 if (IO thread is running)
3480 print 0;
3481 else
3482 print NULL;
3483 }
3484 else
3485 compute Seconds_Behind_Master;
3486 }
3487 else
3488 print NULL;
3489 */
3490
3491
2/2
✓ Branch 0 taken 110119 times.
✓ Branch 1 taken 58153 times.
168272 if (mi->rli->slave_running) {
3492 /*
3493 Check if SQL thread is at the end of relay log
3494 Checking should be done using two conditions
3495 condition1: compare the log positions and
3496 condition2: compare the file names (to handle rotation case)
3497 */
3498
4/4
✓ Branch 0 taken 65597 times.
✓ Branch 1 taken 44522 times.
✓ Branch 2 taken 65385 times.
✓ Branch 3 taken 44734 times.
175716 if ((mi->get_master_log_pos() == mi->rli->get_group_master_log_pos()) &&
3499
2/2
✓ Branch 0 taken 65385 times.
✓ Branch 1 taken 212 times.
65597 (!strcmp(mi->get_master_log_name(),
3500 65597 mi->rli->get_group_master_log_name()))) {
3501
2/2
✓ Branch 0 taken 63640 times.
✓ Branch 1 taken 1745 times.
65385 if (mi->slave_running == MYSQL_SLAVE_RUN_CONNECT)
3502
1/2
✓ Branch 0 taken 63640 times.
✗ Branch 1 not taken.
63640 protocol->store(0LL);
3503 else
3504
1/2
✓ Branch 0 taken 1745 times.
✗ Branch 1 not taken.
1745 protocol->store_null();
3505 } else {
3506 44734 long time_diff = ((long)(time(nullptr) - mi->rli->last_master_timestamp) -
3507 44734 mi->clock_diff_with_master);
3508 /*
3509 Apparently on some systems time_diff can be <0. Here are possible
3510 reasons related to MySQL:
3511 - the master is itself a slave of another master whose time is ahead.
3512 - somebody used an explicit SET TIMESTAMP on the master.
3513 Possible reason related to granularity-to-second of time functions
3514 (nothing to do with MySQL), which can explain a value of -1:
3515 assume the master's and slave's time are perfectly synchronized, and
3516 that at slave's connection time, when the master's timestamp is read,
3517 it is at the very end of second 1, and (a very short time later) when
3518 the slave's timestamp is read it is at the very beginning of second
3519 2. Then the recorded value for master is 1 and the recorded value for
3520 slave is 2. At SHOW REPLICA STATUS time, assume that the difference
3521 between timestamp of slave and rli->last_master_timestamp is 0
3522 (i.e. they are in the same second), then we get 0-(2-1)=-1 as a result.
3523 This confuses users, so we don't go below 0: hence the max().
3524
3525 last_master_timestamp == 0 (an "impossible" timestamp 1970) is a
3526 special marker to say "consider we have caught up".
3527 */
3528
1/2
✓ Branch 0 taken 44734 times.
✗ Branch 1 not taken.
44734 protocol->store(
3529
2/2
✓ Branch 0 taken 41363 times.
✓ Branch 1 taken 3371 times.
89468 (longlong)(mi->rli->last_master_timestamp ? max(0L, time_diff) : 0));
3530 }
3531 } else {
3532
1/2
✓ Branch 0 taken 58153 times.
✗ Branch 1 not taken.
58153 protocol->store_null();
3533 }
3534
3/4
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 168124 times.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
168272 protocol->store(mi->ssl_verify_server_cert ? "Yes" : "No", &my_charset_bin);
3535
3536 // Last_IO_Errno
3537
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->last_error().number);
3538 // Last_IO_Error
3539
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->last_error().message, &my_charset_bin);
3540 // Last_SQL_Errno
3541
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->rli->last_error().number);
3542 // Last_SQL_Error
3543
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->rli->last_error().message, &my_charset_bin);
3544 // Replicate_Ignore_Server_Ids
3545 {
3546 char buff[FN_REFLEN];
3547 ulong i, cur_len;
3548 168272 for (i = 0, buff[0] = 0, cur_len = 0;
3549
3/4
✓ Branch 0 taken 168876 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 604 times.
✓ Branch 3 taken 168272 times.
168876 i < mi->ignore_server_ids->dynamic_ids.size(); i++) {
3550 ulong s_id, slen;
3551 char sbuff[FN_REFLEN];
3552
1/2
✓ Branch 0 taken 604 times.
✗ Branch 1 not taken.
604 s_id = mi->ignore_server_ids->dynamic_ids[i];
3553
2/2
✓ Branch 0 taken 206 times.
✓ Branch 1 taken 398 times.
604 slen = sprintf(sbuff, (i == 0 ? "%lu" : ", %lu"), s_id);
3554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 604 times.
604 if (cur_len + slen + 4 > FN_REFLEN) {
3555 /*
3556 break the loop whenever remained space could not fit
3557 ellipses on the next cycle
3558 */
3559 sprintf(buff + cur_len, "...");
3560 break;
3561 }
3562 604 cur_len += sprintf(buff + cur_len, "%s", sbuff);
3563 }
3564
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(buff, &my_charset_bin);
3565 }
3566 // Master_Server_id
3567
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store((uint32)mi->master_id);
3568
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->master_uuid, &my_charset_bin);
3569 // Master_Info_File
3570
2/4
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
168272 protocol->store(mi->get_description_info(), &my_charset_bin);
3571 // SQL_Delay
3572
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store((uint32)mi->rli->get_sql_delay());
3573 // SQL_Remaining_Delay
3574
2/2
✓ Branch 0 taken 369 times.
✓ Branch 1 taken 167903 times.
168272 if (slave_sql_running_state == stage_sql_thd_waiting_until_delay.m_name) {
3575 369 time_t t = time(nullptr), sql_delay_end = mi->rli->get_sql_delay_end();
3576
3/4
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 369 times.
✗ Branch 3 not taken.
369 protocol->store((uint32)(t < sql_delay_end ? sql_delay_end - t : 0));
3577 } else
3578
1/2
✓ Branch 0 taken 167903 times.
✗ Branch 1 not taken.
167903 protocol->store_null();
3579 // Slave_SQL_Running_State
3580
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(slave_sql_running_state, &my_charset_bin);
3581 // Master_Retry_Count
3582
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store((ulonglong)mi->retry_count);
3583 // Master_Bind
3584
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->bind_addr, &my_charset_bin);
3585 // Last_IO_Error_Timestamp
3586
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->last_error().timestamp, &my_charset_bin);
3587 // Last_SQL_Error_Timestamp
3588
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->rli->last_error().timestamp, &my_charset_bin);
3589 // Master_Ssl_Crl
3590
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->ssl_crl, &my_charset_bin);
3591 // Master_Ssl_Crlpath
3592
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->ssl_crlpath, &my_charset_bin);
3593 // Retrieved_Gtid_Set
3594
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(io_gtid_set_buffer, &my_charset_bin);
3595 // Executed_Gtid_Set
3596
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(sql_gtid_set_buffer, &my_charset_bin);
3597 // Auto_Position
3598
3/4
✓ Branch 0 taken 27882 times.
✓ Branch 1 taken 140390 times.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
168272 protocol->store(mi->is_auto_position() ? 1 : 0);
3599 // Replicate_Rewrite_DB
3600
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 rpl_filter->get_rewrite_db(&tmp);
3601
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(&tmp);
3602 // channel_name
3603
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->get_channel(), &my_charset_bin);
3604 // Master_TLS_Version
3605
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->tls_version, &my_charset_bin);
3606 // Master_public_key_path
3607
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->public_key_path, &my_charset_bin);
3608 // Get_master_public_key
3609
3/4
✓ Branch 0 taken 1151 times.
✓ Branch 1 taken 167121 times.
✓ Branch 2 taken 168272 times.
✗ Branch 3 not taken.
168272 protocol->store(mi->get_public_key ? 1 : 0);
3610
3611
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 protocol->store(mi->network_namespace_str(), &my_charset_bin);
3612
3613
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 rpl_filter->unlock();
3614
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 mysql_mutex_unlock(&mi->rli->err_lock);
3615
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 mysql_mutex_unlock(&mi->err_lock);
3616
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 mysql_mutex_unlock(&mi->rli->data_lock);
3617
1/2
✓ Branch 0 taken 168272 times.
✗ Branch 1 not taken.
168272 mysql_mutex_unlock(&mi->data_lock);
3618
3619 168272 return false;
3620 168272 }
3621
3622 /**
3623 Method to the show the replication status in all channels.
3624
3625 @param[in] thd the client thread
3626
3627 @retval 0 success
3628 @retval 1 Error
3629
3630 */
3631 191914 bool show_slave_status(THD *thd) {
3632 191914 Protocol *protocol = thd->get_protocol();
3633 191914 int sql_gtid_set_size = 0, io_gtid_set_size = 0;
3634 191914 Master_info *mi = nullptr;
3635 191914 char *sql_gtid_set_buffer = nullptr;
3636 char **io_gtid_set_buffer_array;
3637 /*
3638 We need the maximum size of the retrieved gtid set (i.e io_gtid_set_size).
3639 This size is needed to reserve the place in show_slave_status_metadata().
3640 So, we travel all the mi's and find out the maximum size of io_gtid_set_size
3641 and pass it through show_slave_status_metadata()
3642 */
3643 191914 int max_io_gtid_set_size = io_gtid_set_size;
3644 uint idx;
3645 uint num_io_gtid_sets;
3646 191914 bool ret = true;
3647
3648
1/2
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
191914 DBUG_TRACE;
3649
3650
1/2
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
191914 channel_map.assert_some_lock();
3651
3652
1/2
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
191914 num_io_gtid_sets = channel_map.get_num_instances();
3653
3654 io_gtid_set_buffer_array =
3655 383827 (char **)my_malloc(key_memory_show_replica_status_io_gtid_set,
3656
1/2
✓ Branch 0 taken 191913 times.
✗ Branch 1 not taken.
191914 num_io_gtid_sets * sizeof(char *), MYF(MY_WME));
3657
3658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 191913 times.
191913 if (io_gtid_set_buffer_array == nullptr) return true;
3659
3660
1/2
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
191913 global_sid_lock->wrlock();
3661
3662 191914 const Gtid_set *sql_gtid_set = gtid_state->get_executed_gtids();
3663
1/2
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
191914 sql_gtid_set_size = sql_gtid_set->to_string(&sql_gtid_set_buffer);
3664
3665
1/2
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
191914 global_sid_lock->unlock();
3666
3667 191914 idx = 0;
3668
4/6
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 387333 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195419 times.
✓ Branch 5 taken 191914 times.
387333 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
3669 195419 it++) {
3670 195419 mi = it->second;
3671 /*
3672 The following statement is needed because, when mi->host[0]=0
3673 we don't alloc memory for retried_gtid_set. However, we try
3674 to free it at the end, causing a crash. To be on safeside,
3675 we initialize it to NULL, so that my_free() takes care of it.
3676 */
3677 195419 io_gtid_set_buffer_array[idx] = nullptr;
3678
3679
2/2
✓ Branch 0 taken 164202 times.
✓ Branch 1 taken 31217 times.
195419 if (Master_info::is_configured(mi)) {
3680 164202 const Gtid_set *io_gtid_set = mi->rli->get_gtid_set();
3681
1/2
✓ Branch 0 taken 164202 times.
✗ Branch 1 not taken.
164202 mi->rli->get_sid_lock()->wrlock();
3682
3683 /*
3684 @todo: a single memory allocation improves speed,
3685 instead of doing it for each loop
3686 */
3687
3688 164202 if ((io_gtid_set_size =
3689
2/4
✓ Branch 0 taken 164202 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 164202 times.
164202 io_gtid_set->to_string(&io_gtid_set_buffer_array[idx])) < 0) {
3690 my_eof(thd);
3691 my_free(sql_gtid_set_buffer);
3692
3693 for (uint i = 0; i < idx - 1; i++) {
3694 my_free(io_gtid_set_buffer_array[i]);
3695 }
3696 my_free(io_gtid_set_buffer_array);
3697
3698 mi->rli->get_sid_lock()->unlock();
3699 return true;
3700 } else
3701 164202 max_io_gtid_set_size = max_io_gtid_set_size > io_gtid_set_size
3702
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 164062 times.
164202 ? max_io_gtid_set_size
3703 : io_gtid_set_size;
3704
3705
1/2
✓ Branch 0 taken 164202 times.
✗ Branch 1 not taken.
164202 mi->rli->get_sid_lock()->unlock();
3706 }
3707 195419 idx++;
3708 }
3709
3710 191914 mem_root_deque<Item *> field_list(thd->mem_root);
3711
1/2
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
191914 show_slave_status_metadata(&field_list, max_io_gtid_set_size,
3712 sql_gtid_set_size);
3713
3714 // TODO: once the old syntax is removed, remove this as well.
3715
2/2
✓ Branch 0 taken 159966 times.
✓ Branch 1 taken 31948 times.
191914 if (thd->lex->is_replication_deprecated_syntax_used())
3716
1/2
✓ Branch 0 taken 159966 times.
✗ Branch 1 not taken.
159966 rename_fields_use_old_replica_source_terms(thd, field_list);
3717
3718
2/4
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 191914 times.
191914 if (thd->send_result_metadata(field_list,
3719 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) {
3720 goto err;
3721 }
3722
3723 /* Run through each mi */
3724
3725 191914 idx = 0;
3726
4/6
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 387333 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 195419 times.
✓ Branch 5 taken 191914 times.
387333 for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
3727 195419 it++) {
3728 195419 mi = it->second;
3729
3730
2/2
✓ Branch 0 taken 164202 times.
✓ Branch 1 taken 31217 times.
195419 if (Master_info::is_configured(mi)) {
3731
2/4
✓ Branch 0 taken 164202 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 164202 times.
164202 if (show_slave_status_send_data(thd, mi, io_gtid_set_buffer_array[idx],
3732 sql_gtid_set_buffer))
3733 goto err;
3734
3735
2/4
✓ Branch 0 taken 164202 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 164202 times.
164202 if (protocol->end_row()) goto err;
3736 }
3737 195419 idx++;
3738 }
3739
3740 191914 ret = false;
3741 191914 err:
3742
1/2
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
191914 my_eof(thd);
3743
2/2
✓ Branch 0 taken 195419 times.
✓ Branch 1 taken 191914 times.
387333 for (uint i = 0; i < num_io_gtid_sets; i++) {
3744
1/2
✓ Branch 0 taken 195419 times.
✗ Branch 1 not taken.
195419 my_free(io_gtid_set_buffer_array[i]);
3745 }
3746
1/2
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
191914 my_free(io_gtid_set_buffer_array);
3747
1/2
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
191914 my_free(sql_gtid_set_buffer);
3748
3749 191914 return ret;
3750 191914 }
3751
3752 /**
3753 Execute a SHOW REPLICA STATUS statement.
3754
3755 @param thd Pointer to THD object for the client thread executing the
3756 statement.
3757
3758 @param mi Pointer to Master_info object for the IO thread.
3759
3760 @retval false success
3761 @retval true failure
3762
3763 Currently, show slave status works for a channel too, in multisource
3764 replication. But using performance schema tables is better.
3765
3766 */
3767 4081 bool show_slave_status(THD *thd, Master_info *mi) {
3768 4081 Protocol *protocol = thd->get_protocol();
3769 4081 char *sql_gtid_set_buffer = nullptr, *io_gtid_set_buffer = nullptr;
3770 4081 int sql_gtid_set_size = 0, io_gtid_set_size = 0;
3771
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 DBUG_TRACE;
3772
3773
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 if (mi != nullptr) {
3774
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 global_sid_lock->wrlock();
3775 4081 const Gtid_set *sql_gtid_set = gtid_state->get_executed_gtids();
3776
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 sql_gtid_set_size = sql_gtid_set->to_string(&sql_gtid_set_buffer);
3777
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 global_sid_lock->unlock();
3778
3779
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 mi->rli->get_sid_lock()->wrlock();
3780 4081 const Gtid_set *io_gtid_set = mi->rli->get_gtid_set();
3781
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 io_gtid_set_size = io_gtid_set->to_string(&io_gtid_set_buffer);
3782
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 mi->rli->get_sid_lock()->unlock();
3783
3784
2/4
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4081 times.
4081 if (sql_gtid_set_size < 0 || io_gtid_set_size < 0) {
3785 my_eof(thd);
3786 my_free(sql_gtid_set_buffer);
3787 my_free(io_gtid_set_buffer);
3788 return true;
3789 }
3790 }
3791
3792 /* Fill the metadata required for show slave status. */
3793
3794 4081 mem_root_deque<Item *> field_list(thd->mem_root);
3795
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 show_slave_status_metadata(&field_list, io_gtid_set_size, sql_gtid_set_size);
3796
3797 // TODO: once the old syntax is removed, remove this as well.
3798
2/2
✓ Branch 0 taken 4027 times.
✓ Branch 1 taken 54 times.
4081 if (thd->lex->is_replication_deprecated_syntax_used())
3799
1/2
✓ Branch 0 taken 4027 times.
✗ Branch 1 not taken.
4027 rename_fields_use_old_replica_source_terms(thd, field_list);
3800
3801
2/4
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4081 times.
4081 if (thd->send_result_metadata(field_list,
3802 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) {
3803 my_free(sql_gtid_set_buffer);
3804 my_free(io_gtid_set_buffer);
3805 return true;
3806 }
3807
3808
2/2
✓ Branch 0 taken 4070 times.
✓ Branch 1 taken 11 times.
4081 if (Master_info::is_configured(mi)) {
3809
2/4
✓ Branch 0 taken 4070 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4070 times.
4070 if (show_slave_status_send_data(thd, mi, io_gtid_set_buffer,
3810 sql_gtid_set_buffer))
3811 return true;
3812
3813
2/4
✓ Branch 0 taken 4070 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4070 times.
4070 if (protocol->end_row()) {
3814 my_free(sql_gtid_set_buffer);
3815 my_free(io_gtid_set_buffer);
3816 return true;
3817 }
3818 }
3819
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 my_eof(thd);
3820
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 my_free(sql_gtid_set_buffer);
3821
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 my_free(io_gtid_set_buffer);
3822 4081 return false;
3823 4081 }
3824
3825 /**
3826 Entry point for SHOW REPLICA STATUS command. Function displays
3827 the slave status for all channels or for a single channel
3828 based on the FOR CHANNEL clause.
3829
3830 @param[in] thd the client thread.
3831
3832 @retval false ok
3833 @retval true not ok
3834 */
3835 196004 bool show_slave_status_cmd(THD *thd) {
3836 196004 Master_info *mi = nullptr;
3837 196004 LEX *lex = thd->lex;
3838 bool res;
3839
3840
1/2
✓ Branch 0 taken 196004 times.
✗ Branch 1 not taken.
196004 DBUG_TRACE;
3841
3842
1/2
✓ Branch 0 taken 196005 times.
✗ Branch 1 not taken.
196004 channel_map.rdlock();
3843
3844
2/2
✓ Branch 0 taken 191914 times.
✓ Branch 1 taken 4091 times.
196005 if (!lex->mi.for_channel)
3845
1/2
✓ Branch 0 taken 191914 times.
✗ Branch 1 not taken.
191914 res = show_slave_status(thd);
3846 else {
3847
1/2
✓ Branch 0 taken 4091 times.
✗ Branch 1 not taken.
4091 mi = channel_map.get_mi(lex->mi.channel);
3848
3849 /*
3850 When mi is NULL, that means the channel doesn't exist, SSS
3851 will throw an error.
3852 */
3853
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4083 times.
4091 if (mi == nullptr) {
3854
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 my_error(ER_SLAVE_CHANNEL_DOES_NOT_EXIST, MYF(0), lex->mi.channel);
3855
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 channel_map.unlock();
3856 8 return true;
3857 }
3858
3859 /*
3860 If the channel being used is a group replication applier channel we
3861 need to disable the SHOW REPLICA STATUS command as its output is not
3862 compatible with this command.
3863 */
3864
3/4
✓ Branch 0 taken 4083 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4081 times.
4083 if (channel_map.is_group_replication_channel_name(mi->get_channel(),
3865 true)) {
3866
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
3867 "SHOW SLAVE STATUS", mi->get_channel());
3868
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 channel_map.unlock();
3869 2 return true;
3870 }
3871
3872
1/2
✓ Branch 0 taken 4081 times.
✗ Branch 1 not taken.
4081 res = show_slave_status(thd, mi);
3873 }
3874
3875
1/2
✓ Branch 0 taken 195995 times.
✗ Branch 1 not taken.
195995 channel_map.unlock();
3876
3877 195995 return res;
3878 196005 }
3879
3880 90527 void set_slave_thread_options(THD *thd) {
3881
1/2
✓ Branch 0 taken 90527 times.
✗ Branch 1 not taken.
90527 DBUG_TRACE;
3882 /*
3883 It's nonsense to constrain the slave threads with max_join_size; if a
3884 query succeeded on master, we HAVE to execute it. So set
3885 OPTION_BIG_SELECTS. Setting max_join_size to HA_POS_ERROR is not enough
3886 (and it's not needed if we have OPTION_BIG_SELECTS) because an INSERT
3887 SELECT examining more than 4 billion rows would still fail (yes, because
3888 when max_join_size is 4G, OPTION_BIG_SELECTS is automatically set, but
3889 only for client threads.
3890 */
3891 90527 ulonglong options = thd->variables.option_bits | OPTION_BIG_SELECTS;
3892
2/2
✓ Branch 0 taken 87694 times.
✓ Branch 1 taken 2833 times.
90527 if (opt_log_replica_updates)
3893 87694 options |= OPTION_BIN_LOG;
3894 else
3895 2833 options &= ~OPTION_BIN_LOG;
3896 90527 thd->variables.option_bits = options;
3897 90527 thd->variables.completion_type = 0;
3898
3899 /* Do not track GTIDs for slave threads to avoid performance issues. */
3900 90527 thd->variables.session_track_gtids = SESSION_TRACK_GTIDS_OFF;
3901 90527 thd->rpl_thd_ctx.session_gtids_ctx()
3902
1/2
✓ Branch 0 taken 90527 times.
✗ Branch 1 not taken.
90527 .update_tracking_activeness_from_session_variable(thd);
3903
3904 /*
3905 Set autocommit= 1 when info tables are used and autocommit == 0 to
3906 avoid trigger asserts on mysql_execute_command(THD *thd) caused by
3907 info tables updates which do not commit, like Rotate, Stop and
3908 skipped events handling.
3909 */
3910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90527 times.
90527 if ((thd->variables.option_bits & OPTION_NOT_AUTOCOMMIT) &&
3911 (opt_mi_repository_id == INFO_REPOSITORY_TABLE ||
3912 opt_rli_repository_id == INFO_REPOSITORY_TABLE)) {
3913 thd->variables.option_bits |= OPTION_AUTOCOMMIT;
3914 thd->variables.option_bits &= ~OPTION_NOT_AUTOCOMMIT;
3915 thd->server_status |= SERVER_STATUS_AUTOCOMMIT;
3916 }
3917
3918 /*
3919 Set thread InnoDB high priority.
3920 */
3921
6/8
✓ Branch 0 taken 90527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 90517 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
90527 DBUG_EXECUTE_IF("dbug_set_high_prio_sql_thread", {
3922 if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL ||
3923 thd->system_thread == SYSTEM_THREAD_SLAVE_WORKER)
3924 thd->thd_tx_priority = 1;
3925 });
3926 90527 }
3927
3928 31322 void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli) {
3929
1/2
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
31322 DBUG_TRACE;
3930
3931 31322 thd->variables.character_set_client =
3932 31322 global_system_variables.character_set_client;
3933 31322 thd->variables.collation_connection =
3934 31322 global_system_variables.collation_connection;
3935 31322 thd->variables.collation_server = global_system_variables.collation_server;
3936
1/2
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
31322 thd->update_charset();
3937
3938 /*
3939 We use a const cast here since the conceptual (and externally
3940 visible) behavior of the function is to set the default charset of
3941 the thread. That the cache has to be invalidated is a secondary
3942 effect.
3943 */
3944
1/2
✓ Branch 0 taken 31322 times.
✗ Branch 1 not taken.
31322 const_cast<Relay_log_info *>(rli)->cached_charset_invalidate();
3945 31322 }
3946
3947 /*
3948 init_replica_thread()
3949 */
3950
3951 59205 int init_replica_thread(THD *thd, SLAVE_THD_TYPE thd_type) {
3952
1/2
✓ Branch 0 taken 59205 times.
✗ Branch 1 not taken.
59205 DBUG_TRACE;
3953 #if !defined(NDEBUG)
3954 59205 int simulate_error = 0;
3955 #endif
3956 59205 thd->system_thread = (thd_type == SLAVE_THD_WORKER)
3957
2/2
✓ Branch 0 taken 17931 times.
✓ Branch 1 taken 41274 times.
77136 ? SYSTEM_THREAD_SLAVE_WORKER
3958 : (thd_type == SLAVE_THD_SQL)
3959
2/2
✓ Branch 0 taken 10444 times.
✓ Branch 1 taken 7487 times.
17931 ? SYSTEM_THREAD_SLAVE_SQL
3960 : SYSTEM_THREAD_SLAVE_IO;
3961
2/4
✓ Branch 0 taken 59205 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59205 times.
✗ Branch 3 not taken.
59205 thd->get_protocol_classic()->init_net(nullptr);
3962 59205 thd->slave_thread = true;
3963 59205 thd->enable_slow_log = opt_log_slow_replica_statements;
3964
1/2
✓ Branch 0 taken 59205 times.
✗ Branch 1 not taken.
59205 set_slave_thread_options(thd);
3965
3966 /*
3967 Replication threads are:
3968 - background threads in the server, not user sessions,
3969 - yet still assigned a PROCESSLIST_ID,
3970 for historical reasons (displayed in SHOW PROCESSLIST).
3971 */
3972
1/2
✓ Branch 0 taken 59205 times.
✗ Branch 1 not taken.
59205 thd->set_new_thread_id();
3973
3974 #ifdef HAVE_PSI_THREAD_INTERFACE
3975 /*
3976 Populate the PROCESSLIST_ID in the instrumentation.
3977 */
3978
1/2
✓ Branch 0 taken 59205 times.
✗ Branch 1 not taken.
59205 struct PSI_thread *psi = PSI_THREAD_CALL(get_thread)();
3979
1/2
✓ Branch 0 taken 59205 times.
✗ Branch 1 not taken.
59205 PSI_THREAD_CALL(set_thread_id)(psi, thd->thread_id());
3980 #endif /* HAVE_PSI_THREAD_INTERFACE */
3981
3982
3/4
✓ Branch 0 taken 59205 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 59193 times.
59205 DBUG_EXECUTE_IF("simulate_io_replica_error_on_init",
3983 simulate_error |= (1 << SLAVE_THD_IO););
3984
3/4
✓ Branch 0 taken 59205 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 59193 times.
59205 DBUG_EXECUTE_IF("simulate_sql_replica_error_on_init",
3985 simulate_error |= (1 << SLAVE_THD_SQL););
3986
1/2
✓ Branch 0 taken 59205 times.
✗ Branch 1 not taken.
59205 thd->store_globals();
3987 #if !defined(NDEBUG)
3988
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 59193 times.
59205 if (simulate_error & (1 << thd_type)) {
3989 12 return -1;
3990 }
3991 #endif
3992
3993
2/2
✓ Branch 0 taken 10438 times.
✓ Branch 1 taken 48755 times.
59193 if (thd_type == SLAVE_THD_SQL) {
3994
1/2
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
10438 THD_STAGE_INFO(thd, stage_waiting_for_the_next_event_in_relay_log);
3995
1/2
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
10438 thd->set_command(
3996 COM_QUERY); // the SQL thread does not use the server protocol
3997 } else {
3998
1/2
✓ Branch 0 taken 48755 times.
✗ Branch 1 not taken.
48755 THD_STAGE_INFO(thd, stage_waiting_for_source_update);
3999 }
4000
1/2
✓ Branch 0 taken 59193 times.
✗ Branch 1 not taken.
59193 thd->set_time();
4001 /* Do not use user-supplied timeout value for system threads. */
4002 59193 thd->variables.lock_wait_timeout = LONG_TIMEOUT;
4003 59193 return 0;
4004 59205 }
4005
4006 /**
4007 Sleep for a given amount of time or until killed.
4008
4009 @param thd Thread context of the current thread.
4010 @param seconds The number of seconds to sleep.
4011 @param func Function object to check if the thread has been killed.
4012 @param info The Rpl_info object associated with this sleep.
4013
4014 @retval True if the thread has been killed, false otherwise.
4015 */
4016 template <typename killed_func, typename rpl_info>
4017 2794 static inline bool slave_sleep(THD *thd, time_t seconds, killed_func func,
4018 rpl_info info) {
4019 bool ret;
4020 struct timespec abstime;
4021 2794 mysql_mutex_t *lock = &info->sleep_lock;
4022 2794 mysql_cond_t *cond = &info->sleep_cond;
4023
4024 /* Absolute system time at which the sleep time expires. */
4025
1/2
✓ Branch 0 taken 1397 times.
✗ Branch 1 not taken.
2794 set_timespec(&abstime, seconds);
4026
4027
1/2
✓ Branch 0 taken 1397 times.
✗ Branch 1 not taken.
2794 mysql_mutex_lock(lock);
4028
1/2
✓ Branch 0 taken 1397 times.
✗ Branch 1 not taken.
2794 thd->ENTER_COND(cond, lock, nullptr, nullptr);
4029
4030
3/4
✓ Branch 0 taken 1435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1397 times.
✓ Branch 3 taken 38 times.
2870 while (!(ret = func(thd, info))) {
4031
1/2
✓ Branch 0 taken 1397 times.
✗ Branch 1 not taken.
2794 int error = mysql_cond_timedwait(cond, lock, &abstime);
4032
2/2
✓ Branch 0 taken 1359 times.
✓ Branch 1 taken 38 times.
2794 if (is_timeout(error)) break;
4033 }
4034
4035
1/2
✓ Branch 0 taken 1397 times.
✗ Branch 1 not taken.
2794 mysql_mutex_unlock(lock);
4036
1/2
✓ Branch 0 taken 1397 times.
✗ Branch 1 not taken.
2794 thd->EXIT_COND(nullptr);
4037
4038 2794 return ret;
4039 }
4040
4041 /**
4042 Callback function for mysql_binlog_open().
4043
4044 Sets gtid data in the command packet.
4045
4046 @param rpl Replication stream information.
4047 @param packet_gtid_set Pointer to command packet where gtid
4048 data should be stored.
4049 */
4050 2230 static void fix_gtid_set(MYSQL_RPL *rpl, uchar *packet_gtid_set) {
4051 2230 Gtid_set *gtid_set = (Gtid_set *)rpl->gtid_set_arg;
4052
4053 2230 gtid_set->encode(packet_gtid_set);
4054 2230 }
4055
4056 7434 static int request_dump(THD *thd, MYSQL *mysql, MYSQL_RPL *rpl, Master_info *mi,
4057 bool *suppress_warnings) {
4058
1/2
✓ Branch 0 taken 7434 times.
✗ Branch 1 not taken.
7434 DBUG_TRACE;
4059 enum_server_command command =
4060
2/2
✓ Branch 0 taken 2230 times.
✓ Branch 1 taken 5204 times.
7434 mi->is_auto_position() ? COM_BINLOG_DUMP_GTID : COM_BINLOG_DUMP;
4061 /*
4062 Note: binlog_flags is always 0. However, in versions up to 5.6
4063 RC, the master would check the lowest bit and do something
4064 unexpected if it was set; in early versions of 5.6 it would also
4065 use the two next bits. Therefore, for backward compatibility,
4066 if we ever start to use the flags, we should leave the three
4067 lowest bits unused.
4068 */
4069 7434 uint binlog_flags = 0;
4070 7434 binlog_flags |= USE_HEARTBEAT_EVENT_V2;
4071
4072 7434 *suppress_warnings = false;
4073
5/8
✓ Branch 0 taken 7434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5840 times.
✓ Branch 3 taken 1594 times.
✓ Branch 4 taken 1594 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7434 times.
7434 if (RUN_HOOK(binlog_relay_io, before_request_transmit,
4074 (thd, mi, binlog_flags)))
4075 return 1;
4076
4077 7434 rpl->server_id = server_id;
4078 7434 rpl->flags = binlog_flags;
4079
4080
1/2
✓ Branch 0 taken 7434 times.
✗ Branch 1 not taken.
7434 Sid_map sid_map(nullptr); /* No lock needed */
4081 /*
4082 Note: should be declared at the same level as the mysql_binlog_open() call,
4083 as the latter might call fix_gtid_set() which in turns calls
4084 gtid_executed->encode().
4085 */
4086
1/2
✓ Branch 0 taken 7434 times.
✗ Branch 1 not taken.
7434 Gtid_set gtid_executed(&sid_map);
4087
4088
2/2
✓ Branch 0 taken 2230 times.
✓ Branch 1 taken 5204 times.
7434 if (command == COM_BINLOG_DUMP_GTID) {
4089 // get set of GTIDs
4090
1/2
✓ Branch 0 taken 2230 times.
✗ Branch 1 not taken.
2230 mi->rli->get_sid_lock()->wrlock();
4091
4092
2/4
✓ Branch 0 taken 2230 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2230 times.
2230 if (gtid_executed.add_gtid_set(mi->rli->get_gtid_set()) !=
4093 RETURN_STATUS_OK) {
4094 mi->rli->get_sid_lock()->unlock();
4095 return 1;
4096 }
4097
1/2
✓ Branch 0 taken 2230 times.
✗ Branch 1 not taken.
2230 mi->rli->get_sid_lock()->unlock();
4098
4099
1/2
✓ Branch 0 taken 2230 times.
✗ Branch 1 not taken.
2230 global_sid_lock->wrlock();
4100
1/2
✓ Branch 0 taken 2230 times.
✗ Branch 1 not taken.
2230 gtid_state->dbug_print();
4101
4102
2/4
✓ Branch 0 taken 2230 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2230 times.
2230 if (gtid_executed.add_gtid_set(gtid_state->get_executed_gtids()) !=
4103 RETURN_STATUS_OK) {
4104 global_sid_lock->unlock();
4105 return 1;
4106 }
4107
1/2
✓ Branch 0 taken 2230 times.
✗ Branch 1 not taken.
2230 global_sid_lock->unlock();
4108
4109 2230 rpl->file_name = nullptr; /* No need to set rpl.file_name_length */
4110 2230 rpl->start_position = 4;
4111 2230 rpl->flags |= MYSQL_RPL_GTID;
4112
1/2
✓ Branch 0 taken 2230 times.
✗ Branch 1 not taken.
2230 rpl->gtid_set_encoded_size = gtid_executed.get_encoded_length();
4113 2230 rpl->fix_gtid_set = fix_gtid_set;
4114 2230 rpl->gtid_set_arg = (void *)&gtid_executed;
4115 } else {
4116 5204 rpl->file_name_length = 0;
4117 5204 rpl->file_name = mi->get_master_log_name();
4118
2/4
✓ Branch 0 taken 5204 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5204 times.
✗ Branch 3 not taken.
5204 rpl->start_position = DBUG_EVALUATE_IF("request_source_log_pos_3", 3,
4119 mi->get_master_log_pos());
4120 }
4121
2/4
✓ Branch 0 taken 7434 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7434 times.
7434 if (mysql_binlog_open(mysql, rpl)) {
4122 /*
4123 Something went wrong, so we will just reconnect and retry later
4124 in the future, we should do a better error analysis, but for
4125 now we just fill up the error log :-)
4126 */
4127 uint err{mysql_errno(mysql)};
4128 if (err == ER_NET_READ_INTERRUPTED)
4129 *suppress_warnings = true; // Suppress reconnect warning
4130 else
4131 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_ERROR_RETRYING,
4132 Command_names::str_global(command).c_str(), err,
4133 mysql_error(mysql), mi->connect_retry);
4134 if (is_network_error(err)) mi->set_network_error();
4135 return 1;
4136 }
4137
4138 7434 return 0;
4139 7434 }
4140
4141 /**
4142 Read one event from the master.
4143
4144 @param mysql MySQL connection.
4145 @param rpl Replication stream information.
4146 @param mi Master connection information.
4147 @param suppress_warnings true when a normal net read timeout has caused us
4148 to try a reconnect. We do not want to print
4149 anything to the error log in this case because
4150 this an abnormal event in an idle server.
4151
4152 @retval 'packet_error' Error.
4153 @retval number Length of packet.
4154 */
4155
4156 1563204 static ulong read_event(MYSQL *mysql, MYSQL_RPL *rpl, Master_info *mi,
4157 bool *suppress_warnings) {
4158
1/2
✓ Branch 0 taken 1563204 times.
✗ Branch 1 not taken.
1563204 DBUG_TRACE;
4159
4160 1563204 *suppress_warnings = false;
4161 /*
4162 my_real_read() will time us out
4163 We check if we were told to die, and if not, try reading again
4164 */
4165 #ifndef NDEBUG
4166
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1563204 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1563204 times.
1563204 if (disconnect_slave_event_count && !(mi->events_until_exit--))
4167 return packet_error;
4168 #endif
4169
4170
3/4
✓ Branch 0 taken 1563058 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7034 times.
✓ Branch 3 taken 1556024 times.
1563204 if (mysql_binlog_fetch(mysql, rpl)) {
4171
1/2
✓ Branch 0 taken 7034 times.
✗ Branch 1 not taken.
7034 uint err{mysql_errno(mysql)};
4172
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7032 times.
7034 if (err == ER_NET_READ_INTERRUPTED) {
4173 /*
4174 We are trying a normal reconnect after a read timeout;
4175 we suppress prints to .err file as long as the reconnect
4176 happens without problems
4177 */
4178 2 *suppress_warnings = true;
4179
2/2
✓ Branch 0 taken 296 times.
✓ Branch 1 taken 6736 times.
7032 } else if (!mi->abort_slave) {
4180
10/20
✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 296 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 296 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 296 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 296 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 296 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 296 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 296 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 296 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 296 times.
✗ Branch 19 not taken.
296 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_ERROR_READING_FROM_SERVER,
4181 mi->get_for_channel_str(), mysql_error(mysql), err);
4182 }
4183
3/4
✓ Branch 0 taken 7034 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6789 times.
✓ Branch 3 taken 245 times.
7034 if (is_network_error(err)) mi->set_network_error();
4184 7034 return packet_error;
4185 }
4186
4187 /* Check if eof packet */
4188
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 1555939 times.
1556024 if (rpl->size == 0) {
4189
10/20
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 85 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 85 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 85 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 85 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 85 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 85 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 85 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 85 times.
✗ Branch 19 not taken.
85 LogErr(SYSTEM_LEVEL, ER_RPL_SLAVE_DUMP_THREAD_KILLED_BY_MASTER,
4190 mi->get_for_channel_str(), ::server_uuid, mysql_error(mysql));
4191 85 return packet_error;
4192 }
4193
4194
3/8
✓ Branch 0 taken 1555939 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1555939 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1555939 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1555939 DBUG_PRINT("exit", ("len: %lu net->read_pos[4]: %d", rpl->size,
4195 mysql->net.read_pos[4]));
4196 1555939 return rpl->size - 1;
4197 1563058 }
4198
4199 /**
4200 If this is a lagging slave (specified with CHANGE MASTER TO MASTER_DELAY = X),
4201 delays accordingly. Also unlocks rli->data_lock.
4202
4203 Design note: this is the place to unlock rli->data_lock. The lock
4204 must be held when reading delay info from rli, but it should not be
4205 held while sleeping.
4206
4207 @param ev Event that is about to be executed.
4208
4209 @param thd The sql thread's THD object.
4210
4211 @param rli The sql thread's Relay_log_info structure.
4212
4213 @retval 0 If the delay timed out and the event shall be executed.
4214
4215 @retval nonzero If the delay was interrupted and the event shall be skipped.
4216 */
4217 1810846 static int sql_delay_event(Log_event *ev, THD *thd, Relay_log_info *rli) {
4218 1810846 time_t sql_delay = rli->get_sql_delay();
4219
4220
1/2
✓ Branch 0 taken 1810846 times.
✗ Branch 1 not taken.
1810846 DBUG_TRACE;
4221 1810846 mysql_mutex_assert_owner(&rli->data_lock);
4222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1810846 times.
1810846 assert(!rli->belongs_to_client());
4223
4224
2/2
✓ Branch 0 taken 840 times.
✓ Branch 1 taken 1810006 times.
1810846 if (sql_delay) {
4225 840 int type = ev->get_type_code();
4226 840 time_t sql_delay_end = 0;
4227
4228
3/4
✓ Branch 0 taken 840 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 761 times.
840 if (DBUG_EVALUATE_IF("sql_delay_without_timestamps", 1, 0)) {
4229 79 rli->commit_timestamps_status = Relay_log_info::COMMIT_TS_NOT_FOUND;
4230 }
4231
4/4
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 640 times.
✓ Branch 2 taken 176 times.
✓ Branch 3 taken 24 times.
840 if (rli->commit_timestamps_status == Relay_log_info::COMMIT_TS_UNKNOWN &&
4232
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 173 times.
176 (type == binary_log::GTID_LOG_EVENT ||
4233 type == binary_log::ANONYMOUS_GTID_LOG_EVENT)) {
4234
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
27 if (static_cast<Gtid_log_event *>(ev)->has_commit_timestamps) {
4235 27 rli->commit_timestamps_status = Relay_log_info::COMMIT_TS_FOUND;
4236 } else {
4237 rli->commit_timestamps_status = Relay_log_info::COMMIT_TS_NOT_FOUND;
4238 }
4239 }
4240
4241
2/2
✓ Branch 0 taken 588 times.
✓ Branch 1 taken 252 times.
840 if (rli->commit_timestamps_status == Relay_log_info::COMMIT_TS_FOUND) {
4242
4/4
✓ Branch 0 taken 449 times.
✓ Branch 1 taken 139 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 444 times.
588 if (type == binary_log::GTID_LOG_EVENT ||
4243 type == binary_log::ANONYMOUS_GTID_LOG_EVENT) {
4244 /*
4245 Calculate when we should execute the event.
4246 The immediate master timestamp is expressed in microseconds.
4247 Delayed replication is defined in seconds.
4248 Hence convert immediate_commit_timestamp to seconds here.
4249 */
4250
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 sql_delay_end = ceil((static_cast<Gtid_log_event *>(ev)
4251 144 ->immediate_commit_timestamp) /
4252 144 1000000.00) +
4253 sql_delay;
4254 }
4255 } else {
4256 /*
4257 the immediate master does not support commit timestamps
4258 in Gtid_log_events
4259 */
4260
4/4
✓ Branch 0 taken 183 times.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 75 times.
✓ Branch 3 taken 108 times.
252 if (type != binary_log::ROTATE_EVENT &&
4261
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 type != binary_log::FORMAT_DESCRIPTION_EVENT &&
4262
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 type != binary_log::PREVIOUS_GTIDS_LOG_EVENT &&
4263 type != binary_log::START_5_7_ENCRYPTION_EVENT) {
4264 // Calculate when we should execute the event.
4265 75 sql_delay_end = ev->common_header->when.tv_sec +
4266 75 rli->mi->clock_diff_with_master + sql_delay;
4267 }
4268 }
4269
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 621 times.
840 if (sql_delay_end != 0) {
4270 // The current time.
4271 219 time_t now = time(nullptr);
4272 // The amount of time we will have to sleep before executing the event.
4273 219 time_t nap_time = 0;
4274
4275
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 59 times.
219 if (sql_delay_end > now) {
4276 160 nap_time = sql_delay_end - now;
4277
4278
3/8
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 160 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
160 DBUG_PRINT("info",
4279 ("sql_delay= %lu "
4280 "now= %ld "
4281 "sql_delay_end= %ld "
4282 "nap_time= %ld",
4283 sql_delay, (long)now, (long)sql_delay_end, (long)nap_time));
4284
3/8
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 160 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
160 DBUG_PRINT("info", ("delaying replication event %lu secs", nap_time));
4285
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 rli->start_sql_delay(sql_delay_end);
4286
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 mysql_mutex_unlock(&rli->data_lock);
4287
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 return slave_sleep(thd, nap_time, sql_slave_killed, rli);
4288 } else {
4289
3/8
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 59 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
59 DBUG_PRINT("info", ("sql_delay= %lu "
4290 "now= %ld "
4291 "sql_delay_end= %ld ",
4292 sql_delay, (long)now, (long)sql_delay_end));
4293 }
4294 }
4295 }
4296
1/2
✓ Branch 0 taken 1810686 times.
✗ Branch 1 not taken.
1810686 mysql_mutex_unlock(&rli->data_lock);
4297 1810686 return 0;
4298 1810846 }
4299
4300 /**
4301 Applies the given event and advances the relay log position.
4302
4303 This is needed by the sql thread to execute events from the binlog,
4304 and by clients executing BINLOG statements. Conceptually, this
4305 function does:
4306
4307 @code
4308 ev->apply_event(rli);
4309 ev->update_pos(rli);
4310 @endcode
4311
4312 It also does the following maintenance:
4313
4314 - Initializes the thread's server_id and time; and the event's
4315 thread.
4316
4317 - If !rli->belongs_to_client() (i.e., if it belongs to the slave
4318 sql thread instead of being used for executing BINLOG
4319 statements), it does the following things: (1) skips events if it
4320 is needed according to the server id or slave_skip_counter; (2)
4321 unlocks rli->data_lock; (3) sleeps if required by 'CHANGE MASTER
4322 TO MASTER_DELAY=X'; (4) maintains the running state of the sql
4323 thread (rli->thread_state).
4324
4325 - Reports errors as needed.
4326
4327 @param ptr_ev a pointer to a reference to the event to apply.
4328
4329 @param thd The client thread that executes the event (i.e., the
4330 slave sql thread if called from a replication slave, or the client
4331 thread if called to execute a BINLOG statement).
4332
4333 @param rli The relay log info (i.e., the slave's rli if called from
4334 a replication slave, or the client's thd->rli_fake if called to
4335 execute a BINLOG statement).
4336
4337 @note MTS can store NULL to @c ptr_ev location to indicate
4338 the event is taken over by a Worker.
4339
4340 @retval SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK
4341 OK.
4342
4343 @retval SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPLY_ERROR
4344 Error calling ev->apply_event().
4345
4346 @retval SLAVE_APPLY_EVENT_AND_UPDATE_POS_UPDATE_POS_ERROR
4347 No error calling ev->apply_event(), but error calling
4348 ev->update_pos().
4349
4350 @retval SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPEND_JOB_ERROR
4351 append_item_to_jobs() failed, thread was killed while waiting
4352 for successful enqueue on worker.
4353 */
4354 static enum enum_slave_apply_event_and_update_pos_retval
4355 1863626 apply_event_and_update_pos(Log_event **ptr_ev, THD *thd, Relay_log_info *rli) {
4356 1863626 int exec_res = 0;
4357 1863626 bool skip_event = false;
4358 1863626 Log_event *ev = *ptr_ev;
4359 1863626 Log_event::enum_skip_reason reason = Log_event::EVENT_SKIP_NOT;
4360
4361
1/2
✓ Branch 0 taken 1863626 times.
✗ Branch 1 not taken.
1863626 DBUG_TRACE;
4362
4363
3/10
✓ Branch 0 taken 1863626 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1863626 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1863626 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1863626 DBUG_PRINT("exec_event",
4364 ("%s(type_code: %d; server_id: %d)", ev->get_type_str(),
4365 ev->get_type_code(), ev->server_id));
4366
3/12
✓ Branch 0 taken 1863626 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1863626 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1863626 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1863626 DBUG_PRINT("info",
4367 ("thd->options: %s%s; rli->last_event_start_time: %lu",
4368 FLAGSTR(thd->variables.option_bits, OPTION_NOT_AUTOCOMMIT),
4369 FLAGSTR(thd->variables.option_bits, OPTION_BEGIN),
4370 (ulong)rli->last_event_start_time));
4371
4372 /*
4373 Execute the event to change the database and update the binary
4374 log coordinates, but first we set some data that is needed for
4375 the thread.
4376
4377 The event will be executed unless it is supposed to be skipped.
4378
4379 Queries originating from this server must be skipped. Low-level
4380 events (Format_description_log_event, Rotate_log_event,
4381 Stop_log_event) from this server must also be skipped. But for
4382 those we don't want to modify 'group_master_log_pos', because
4383 these events did not exist on the master.
4384 Format_description_log_event is not completely skipped.
4385
4386 Skip queries specified by the user in 'slave_skip_counter'. We
4387 can't however skip events that has something to do with the log
4388 files themselves.
4389
4390 Filtering on own server id is extremely important, to ignore
4391 execution of events created by the creation/rotation of the relay
4392 log (remember that now the relay log starts with its Format_desc,
4393 has a Rotate etc).
4394 */
4395 /*
4396 Set the unmasked and actual server ids from the event
4397 */
4398 1863626 thd->server_id = ev->server_id; // use the original server id for logging
4399 1863626 thd->unmasked_server_id = ev->common_header->unmasked_server_id;
4400
1/2
✓ Branch 0 taken 1863626 times.
✗ Branch 1 not taken.
1863626 thd->set_time(); // time the query
4401
1/2
✓ Branch 0 taken 1863626 times.
✗ Branch 1 not taken.
1863626 thd->lex->set_current_query_block(nullptr);
4402
2/2
✓ Branch 0 taken 14028 times.
✓ Branch 1 taken 1849598 times.
1863626 if (!ev->common_header->when.tv_sec)
4403 14028 my_micro_time_to_timeval(my_micro_time(), &ev->common_header->when);
4404 1863626 ev->thd = thd; // because up to this point, ev->thd == 0
4405
4406
4/4
✓ Branch 0 taken 1060 times.
✓ Branch 1 taken 1862566 times.
✓ Branch 2 taken 1862696 times.
✓ Branch 3 taken 930 times.
1864686 if (!(rli->is_mts_recovery() &&
4407
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 930 times.
1060 bitmap_is_set(&rli->recovery_groups, rli->mts_recovery_index))) {
4408
1/2
✓ Branch 0 taken 1862696 times.
✗ Branch 1 not taken.
1862696 reason = ev->shall_skip(rli);
4409 }
4410 #ifndef NDEBUG
4411
2/2
✓ Branch 0 taken 1060 times.
✓ Branch 1 taken 1862566 times.
1863626 if (rli->is_mts_recovery()) {
4412
3/10
✓ Branch 0 taken 1060 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1060 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1060 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1060 DBUG_PRINT("mts",
4413 ("Mts is recovering %d, number of bits set %d, "
4414 "bitmap is set %d, index %lu.\n",
4415 rli->is_mts_recovery(), bitmap_bits_set(&rli->recovery_groups),
4416 bitmap_is_set(&rli->recovery_groups, rli->mts_recovery_index),
4417 rli->mts_recovery_index));
4418 }
4419 #endif
4420
2/2
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 1863140 times.
1863626 if (reason == Log_event::EVENT_SKIP_COUNT) {
4421 486 --rli->slave_skip_counter;
4422 486 skip_event = true;
4423 }
4424
1/2
✓ Branch 0 taken 1863626 times.
✗ Branch 1 not taken.
1863626 set_timespec_nsec(&rli->ts_exec[0], 0);
4425 1863626 rli->stats_read_time += diff_timespec(&rli->ts_exec[0], &rli->ts_exec[1]);
4426
4427
2/2
✓ Branch 0 taken 1810846 times.
✓ Branch 1 taken 52780 times.
1863626 if (reason == Log_event::EVENT_SKIP_NOT) {
4428 // Sleeps if needed, and unlocks rli->data_lock.
4429
3/4
✓ Branch 0 taken 1810846 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1810843 times.
1810846 if (sql_delay_event(ev, thd, rli))
4430 3 return SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK;
4431
4432
1/2
✓ Branch 0 taken 1810633 times.
✗ Branch 1 not taken.
1810843 exec_res = ev->apply_event(rli);
4433
4434
8/10
✓ Branch 0 taken 1810633 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1810628 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
1810633 DBUG_EXECUTE_IF("simulate_stop_when_mta_in_group",
4435 if (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP &&
4436 rli->curr_group_seen_begin)
4437 DBUG_SET("+d,stop_when_mta_in_group"););
4438
4439
4/4
✓ Branch 0 taken 1810489 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 1723306 times.
✓ Branch 3 taken 87183 times.
1810633 if (!exec_res && (ev->worker != rli)) {
4440
2/2
✓ Branch 0 taken 1106634 times.
✓ Branch 1 taken 616672 times.
1723306 if (ev->worker) {
4441 1106634 Slave_job_item item = {ev, rli->get_event_relay_log_number(),
4442 1106634 rli->get_event_start_pos()};
4443 1106634 Slave_job_item *job_item = &item;
4444 1106634 Slave_worker *w = (Slave_worker *)ev->worker;
4445 // specially marked group typically with OVER_MAX_DBS_IN_EVENT_MTS db:s
4446 1106634 bool need_sync = ev->is_mts_group_isolated();
4447
4448 // all events except BEGIN-query must be marked with a non-NULL Worker
4449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1106634 times.
1106634 assert(((Slave_worker *)ev->worker) == rli->last_assigned_worker);
4450
4451
3/8
✓ Branch 0 taken 1106634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1106634 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1106634 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1106634 DBUG_PRINT("Log_event::apply_event:",
4452 ("-> job item data %p to W_%lu", job_item->data, w->id));
4453
4454 // Reset mts in-group state
4455
2/2
✓ Branch 0 taken 327613 times.
✓ Branch 1 taken 779021 times.
1106634 if (rli->mts_group_status == Relay_log_info::MTS_END_GROUP) {
4456 // CGAP cleanup
4457
1/2
✓ Branch 0 taken 327613 times.
✗ Branch 1 not taken.
327613 rli->curr_group_assigned_parts.clear();
4458 // reset the B-group and Gtid-group marker
4459 327613 rli->curr_group_seen_begin = rli->curr_group_seen_gtid = false;
4460 327613 rli->last_assigned_worker = nullptr;
4461 }
4462 /*
4463 Storing GAQ index of the group that the event belongs to
4464 in the event. Deferred events are handled similarly below.
4465 */
4466 1106634 ev->mts_group_idx = rli->gaq->assigned_group_index;
4467
4468 1106634 bool append_item_to_jobs_error = false;
4469
3/4
✓ Branch 0 taken 1106634 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 327552 times.
✓ Branch 3 taken 779082 times.
1106634 if (rli->curr_group_da.size() > 0) {
4470 /*
4471 the current event sorted out which partition the current group
4472 belongs to. It's time now to processed deferred array events.
4473 */
4474
3/4
✓ Branch 0 taken 944180 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 616628 times.
✓ Branch 3 taken 327552 times.
944180 for (uint i = 0; i < rli->curr_group_da.size(); i++) {
4475
1/2
✓ Branch 0 taken 616628 times.
✗ Branch 1 not taken.
616628 Slave_job_item da_item = rli->curr_group_da[i];
4476
3/8
✓ Branch 0 taken 616628 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 616628 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 616628 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
616628 DBUG_PRINT("mts", ("Assigning job %llu to worker %lu",
4477 (da_item.data)->common_header->log_pos, w->id));
4478 616628 da_item.data->mts_group_idx =
4479 616628 rli->gaq->assigned_group_index; // similarly to above
4480
2/2
✓ Branch 0 taken 616627 times.
✓ Branch 1 taken 1 times.
616628 if (!append_item_to_jobs_error)
4481
1/2
✓ Branch 0 taken 616627 times.
✗ Branch 1 not taken.
616627 append_item_to_jobs_error = append_item_to_jobs(&da_item, w, rli);
4482
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 616626 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
616628 if (append_item_to_jobs_error) delete da_item.data;
4483 }
4484
1/2
✓ Branch 0 taken 327552 times.
✗ Branch 1 not taken.
327552 rli->curr_group_da.clear();
4485 }
4486
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1106633 times.
1106634 if (append_item_to_jobs_error)
4487 2 return SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPEND_JOB_ERROR;
4488
4489
3/8
✓ Branch 0 taken 1106633 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1106633 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1106633 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1106633 DBUG_PRINT("mts", ("Assigning job %llu to worker %lu\n",
4490 job_item->data->common_header->log_pos, w->id));
4491
4492 /* Notice `ev' instance can be destroyed after `append()' */
4493
3/4
✓ Branch 0 taken 1106633 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1106632 times.
1106633 if (append_item_to_jobs(job_item, w, rli))
4494 1 return SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPEND_JOB_ERROR;
4495
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 1106604 times.
1106632 if (need_sync) {
4496 /*
4497 combination of over-max db:s and end of the current group
4498 forces to wait for the assigned groups completion by assigned
4499 to the event worker.
4500 Indeed MTS group status could be safely set to MTS_NOT_IN_GROUP
4501 after wait_() returns.
4502 No need to know a possible error out of synchronization call.
4503 */
4504
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 (void)rli->current_mts_submode->wait_for_workers_to_finish(rli);
4505 }
4506 }
4507 1723304 *ptr_ev = nullptr; // announcing the event is passed to w-worker
4508
4509
6/8
✓ Branch 0 taken 1723304 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1723304 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1083 times.
✓ Branch 5 taken 1722221 times.
✓ Branch 6 taken 1083 times.
✓ Branch 7 taken 1722221 times.
1723304 if (rli->is_parallel_exec() && rli->mts_events_assigned % 1024 == 1) {
4510 1083 time_t my_now = time(nullptr);
4511
4512
2/2
✓ Branch 0 taken 151 times.
✓ Branch 1 taken 932 times.
1083 if ((my_now - rli->mts_last_online_stat) >= mts_online_stat_period) {
4513
9/18
✓ Branch 0 taken 151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 151 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 151 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 151 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 151 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 151 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 151 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 151 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 151 times.
✗ Branch 17 not taken.
302 LogErr(INFORMATION_LEVEL, ER_RPL_MTS_STATISTICS,
4514 rli->get_for_channel_str(),
4515 static_cast<unsigned long>(my_now - rli->mts_last_online_stat),
4516 rli->mts_events_assigned, rli->mts_wq_overrun_cnt,
4517 rli->mts_wq_overfill_cnt, rli->wq_size_waits_cnt,
4518 rli->mts_total_wait_overlap.load(),
4519 rli->mts_wq_no_underrun_cnt, rli->mts_total_wait_worker_avail);
4520 151 rli->mts_last_online_stat = my_now;
4521 }
4522 }
4523 }
4524 } else
4525
1/2
✓ Branch 0 taken 52780 times.
✗ Branch 1 not taken.
52780 mysql_mutex_unlock(&rli->data_lock);
4526
4527
1/2
✓ Branch 0 taken 1863411 times.
✗ Branch 1 not taken.
1863411 set_timespec_nsec(&rli->ts_exec[1], 0);
4528 1863411 rli->stats_exec_time += diff_timespec(&rli->ts_exec[1], &rli->ts_exec[0]);
4529
4530
3/8
✓ Branch 0 taken 1863411 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1863411 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1863411 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1863411 DBUG_PRINT("info", ("apply_event error = %d", exec_res));
4531
2/2
✓ Branch 0 taken 1863267 times.
✓ Branch 1 taken 144 times.
1863411 if (exec_res == 0) {
4532 /*
4533 Positions are not updated here when an XID is processed. To make
4534 a slave crash-safe, positions must be updated while processing a
4535 XID event and as such do not need to be updated here again.
4536
4537 However, if the event needs to be skipped, this means that it
4538 will not be processed and then positions need to be updated here.
4539
4540 DDL:s that are not yet committed, as indicated by
4541 @c has_ddl_committed flag, visit the block.
4542
4543 See sql/rpl_rli.h for further details.
4544 */
4545 1863267 int error = 0;
4546
6/6
✓ Branch 0 taken 139963 times.
✓ Branch 1 taken 1723304 times.
✓ Branch 2 taken 139470 times.
✓ Branch 3 taken 493 times.
✓ Branch 4 taken 139886 times.
✓ Branch 5 taken 1723381 times.
2143193 if (*ptr_ev &&
4547 139963 ((ev->get_type_code() != binary_log::XID_EVENT &&
4548
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 139470 times.
✓ Branch 2 taken 179 times.
✓ Branch 3 taken 314 times.
139963 !is_committed_ddl(*ptr_ev)) ||
4549
2/2
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 58 times.
179 skip_event ||
4550
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
300 (rli->is_mts_recovery() && !is_gtid_event(ev) &&
4551
4/8
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 121 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 102 times.
✓ Branch 7 taken 19 times.
242 (ev->ends_group() || !rli->mts_recovery_group_seen_begin) &&
4552 121 bitmap_is_set(&rli->recovery_groups, rli->mts_recovery_index)))) {
4553 #ifndef NDEBUG
4554 /*
4555 This only prints information to the debug trace.
4556
4557 TODO: Print an informational message to the error log?
4558 */
4559 static const char *const explain[] = {
4560 // EVENT_SKIP_NOT,
4561 "not skipped",
4562 // EVENT_SKIP_IGNORE,
4563 "skipped because event should be ignored",
4564 // EVENT_SKIP_COUNT
4565 "skipped because event skip counter was non-zero"};
4566
3/8
✓ Branch 0 taken 139886 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 139886 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 139886 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
139886 DBUG_PRINT("info",
4567 ("OPTION_BEGIN: %d; IN_STMT: %d",
4568 static_cast<bool>(thd->variables.option_bits & OPTION_BEGIN),
4569 rli->get_flag(Relay_log_info::IN_STMT)));
4570
3/10
✓ Branch 0 taken 139886 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 139886 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 139886 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
139886 DBUG_PRINT("skip_event",
4571 ("%s event was %s", ev->get_type_str(), explain[reason]));
4572 #endif
4573
4574
1/2
✓ Branch 0 taken 139886 times.
✗ Branch 1 not taken.
139886 error = ev->update_pos(rli);
4575 /*
4576 Slave skips an event if the slave_skip_counter is greater than zero.
4577 We have to free thd's mem_root here after we update the positions
4578 in the repository table if the event is a skipped event.
4579 Otherwise, imagine a situation where slave_skip_counter is big number
4580 and slave is skipping the events and updating the repository.
4581 All the memory used while these operations are going on is never
4582 freed unless slave starts executing the events (after slave_skip_counter
4583 becomes zero).
4584
4585 Hence we free thd's mem_root here if it is a skipped event.
4586 (freeing mem_root generally happens from Query_log_event::do_apply_event
4587 or Rows_log_event::do_apply_event when they find the end of
4588 the group event).
4589 */
4590
3/4
✓ Branch 0 taken 486 times.
✓ Branch 1 taken 139400 times.
✓ Branch 2 taken 486 times.
✗ Branch 3 not taken.
139886 if (skip_event) thd->mem_root->ClearForReuse();
4591
4592 #ifndef NDEBUG
4593
3/8
✓ Branch 0 taken 139886 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 139886 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 139886 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
139886 DBUG_PRINT("info", ("update_pos error = %d", error));
4594
1/2
✓ Branch 0 taken 139886 times.
✗ Branch 1 not taken.
139886 if (!rli->belongs_to_client()) {
4595 char buf[22];
4596
3/10
✓ Branch 0 taken 139886 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 139886 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 139886 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
139886 DBUG_PRINT("info",
4597 ("group %s %s", llstr(rli->get_group_relay_log_pos(), buf),
4598 rli->get_group_relay_log_name()));
4599
3/10
✓ Branch 0 taken 139886 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 139886 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 139886 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
139886 DBUG_PRINT("info",
4600 ("event %s %s", llstr(rli->get_event_relay_log_pos(), buf),
4601 rli->get_event_relay_log_name()));
4602 }
4603 #endif
4604 } else {
4605 /*
4606 INTVAR_EVENT, RAND_EVENT, USER_VAR_EVENT and ROWS_QUERY_LOG_EVENT are
4607 deferred event. It means ev->worker is NULL.
4608 */
4609
4/16
✓ Branch 0 taken 1723304 times.
✓ Branch 1 taken 77 times.
✓ Branch 2 taken 1723304 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1723304 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
1723381 assert(*ptr_ev == ev || rli->is_parallel_exec() ||
4610 (!ev->worker &&
4611 (ev->get_type_code() == binary_log::INTVAR_EVENT ||
4612 ev->get_type_code() == binary_log::RAND_EVENT ||
4613 ev->get_type_code() == binary_log::USER_VAR_EVENT ||
4614 ev->get_type_code() == binary_log::ROWS_QUERY_LOG_EVENT)));
4615
4616 1723381 rli->inc_event_relay_log_pos();
4617 }
4618
4619
4/4
✓ Branch 0 taken 1059 times.
✓ Branch 1 taken 1862208 times.
✓ Branch 2 taken 1044 times.
✓ Branch 3 taken 15 times.
1864326 if (!error && rli->is_mts_recovery() &&
4620
2/2
✓ Branch 0 taken 1014 times.
✓ Branch 1 taken 30 times.
2103 ev->get_type_code() != binary_log::ROTATE_EVENT &&
4621
2/2
✓ Branch 0 taken 999 times.
✓ Branch 1 taken 15 times.
2058 ev->get_type_code() != binary_log::FORMAT_DESCRIPTION_EVENT &&
4622
4/6
✓ Branch 0 taken 1863267 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 999 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 999 times.
✓ Branch 5 taken 1862268 times.
3727548 ev->get_type_code() != binary_log::PREVIOUS_GTIDS_LOG_EVENT &&
4623 999 ev->get_type_code() != binary_log::START_5_7_ENCRYPTION_EVENT) {
4624
3/4
✓ Branch 0 taken 999 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 134 times.
✓ Branch 3 taken 865 times.
999 if (ev->starts_group()) {
4625 134 rli->mts_recovery_group_seen_begin = true;
4626
7/8
✓ Branch 0 taken 865 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 729 times.
✓ Branch 3 taken 136 times.
✓ Branch 4 taken 362 times.
✓ Branch 5 taken 367 times.
✓ Branch 6 taken 250 times.
✓ Branch 7 taken 615 times.
1363 } else if ((ev->ends_group() || !rli->mts_recovery_group_seen_begin) &&
4627
2/2
✓ Branch 0 taken 250 times.
✓ Branch 1 taken 248 times.
498 !is_gtid_event(ev)) {
4628 250 rli->mts_recovery_index++;
4629
2/2
✓ Branch 0 taken 215 times.
✓ Branch 1 taken 35 times.
250 if (--rli->mts_recovery_group_cnt == 0) {
4630 215 rli->mts_recovery_index = 0;
4631
9/18
✓ Branch 0 taken 215 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 215 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 215 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 215 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 215 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 215 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 215 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 215 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 215 times.
✗ Branch 17 not taken.
215 LogErr(INFORMATION_LEVEL, ER_RPL_MTS_RECOVERY_COMPLETE,
4632 rli->get_for_channel_str(), rli->get_group_relay_log_name(),
4633 rli->get_group_relay_log_pos(),
4634 rli->get_group_master_log_name(),
4635 rli->get_group_master_log_pos());
4636 /*
4637 Few tests wait for UNTIL_SQL_AFTER_MTS_GAPS completion.
4638 Due to existing convention the status won't change
4639 prior to slave restarts.
4640 So making of UNTIL_SQL_AFTER_MTS_GAPS completion is done here,
4641 and only in the debug build to make the test to catch the change
4642 despite a faulty design of UNTIL checking before execution.
4643 */
4644
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 133 times.
215 if (rli->until_condition ==
4645 Relay_log_info::UNTIL_SQL_AFTER_MTS_GAPS) {
4646 82 rli->until_condition = Relay_log_info::UNTIL_DONE;
4647 }
4648 // reset the Worker tables to remove last slave session time info
4649
2/4
✓ Branch 0 taken 215 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 215 times.
215 if ((error = rli->mts_finalize_recovery())) {
4650 (void)Rpl_info_factory::reset_workers(rli);
4651 }
4652 }
4653 250 rli->mts_recovery_group_seen_begin = false;
4654
1/2
✓ Branch 0 taken 250 times.
✗ Branch 1 not taken.
250 if (!error)
4655
1/2
✓ Branch 0 taken 250 times.
✗ Branch 1 not taken.
250 error = rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT);
4656 }
4657 }
4658
4659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1863267 times.
1863267 if (error) {
4660 /*
4661 The update should not fail, so print an error message and
4662 return an error code.
4663
4664 TODO: Replace this with a decent error message when merged
4665 with BUG#24954 (which adds several new error message).
4666 */
4667 char buf[22];
4668 rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR,
4669 "It was not possible to update the positions"
4670 " of the relay log information: the slave may"
4671 " be in an inconsistent state."
4672 " Stopped in %s position %s",
4673 rli->get_group_relay_log_name(),
4674 llstr(rli->get_group_relay_log_pos(), buf));
4675 return SLAVE_APPLY_EVENT_AND_UPDATE_POS_UPDATE_POS_ERROR;
4676 }
4677 }
4678
4679
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 1863267 times.
1863411 return exec_res ? SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPLY_ERROR
4680 1863411 : SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK;
4681 1863416 }
4682
4683 /**
4684 Let the worker applying the current group to rollback and gracefully
4685 finish its work before.
4686
4687 @param rli The slave's relay log info.
4688
4689 @param ev a pointer to the event on hold before applying this rollback
4690 procedure.
4691
4692 @retval false The rollback succeeded.
4693
4694 @retval true There was an error while injecting events.
4695 */
4696 40 static bool coord_handle_partial_binlogged_transaction(Relay_log_info *rli,
4697 const Log_event *ev) {
4698
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 DBUG_TRACE;
4699 /*
4700 This function is called holding the rli->data_lock.
4701 We must return it still holding this lock, except in the case of returning
4702 error.
4703 */
4704 40 mysql_mutex_assert_owner(&rli->data_lock);
4705 40 THD *thd = rli->info_thd;
4706
4707
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 28 times.
40 if (!rli->curr_group_seen_begin) {
4708
3/8
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
12 DBUG_PRINT("info", ("Injecting QUERY(BEGIN) to rollback worker"));
4709 Log_event *begin_event = new Query_log_event(thd, STRING_WITH_LEN("BEGIN"),
4710 true, /* using_trans */
4711 false, /* immediate */
4712 true, /* suppress_use */
4713 0, /* error */
4714
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 true /* ignore_command */);
4715 12 ((Query_log_event *)begin_event)->db = "";
4716 12 begin_event->common_header->data_written = 0;
4717 12 begin_event->server_id = ev->server_id;
4718 /*
4719 This event is not generated on master and is only specific to replicas.
4720 So, we don't want this BEGIN query to respect MASTER_DELAY.
4721 Make the timestamp to be same as that of the FORMAT_DESCRIPTION_EVENT
4722 event which triggered this.
4723 */
4724 12 begin_event->common_header->when = ev->common_header->when;
4725 /*
4726 We must be careful to avoid SQL thread increasing its position
4727 farther than the event that triggered this QUERY(BEGIN).
4728 */
4729 12 begin_event->common_header->log_pos = ev->common_header->log_pos;
4730 12 begin_event->future_event_relay_log_pos = ev->future_event_relay_log_pos;
4731
4732
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (apply_event_and_update_pos(&begin_event, thd, rli) !=
4733 SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK) {
4734 delete begin_event;
4735 return true;
4736 }
4737
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 mysql_mutex_lock(&rli->data_lock);
4738 }
4739
4740
3/8
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 40 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
40 DBUG_PRINT("info", ("Injecting QUERY(ROLLBACK) to rollback worker"));
4741 Log_event *rollback_event = new Query_log_event(
4742 thd, STRING_WITH_LEN("ROLLBACK"), true, /* using_trans */
4743 false, /* immediate */
4744 true, /* suppress_use */
4745 0, /* error */
4746
2/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 true /* ignore_command */);
4747 40 ((Query_log_event *)rollback_event)->db = "";
4748 40 rollback_event->common_header->data_written = 0;
4749 40 rollback_event->server_id = ev->server_id;
4750 /*
4751 This event is not generated on master and is only specific to replicas.
4752 So, we don't want this ROLLBACK query to respect MASTER_DELAY.
4753 Make the timestamp to be same as that of the FORMAT_DESCRIPTION_EVENT
4754 event which triggered this.
4755 */
4756 40 rollback_event->common_header->when = ev->common_header->when;
4757 /*
4758 We must be careful to avoid SQL thread increasing its position
4759 farther than the event that triggered this QUERY(ROLLBACK).
4760 */
4761 40 rollback_event->common_header->log_pos = ev->common_header->log_pos;
4762 40 rollback_event->future_event_relay_log_pos = ev->future_event_relay_log_pos;
4763
4764 40 ((Query_log_event *)rollback_event)->rollback_injected_by_coord = true;
4765
4766
2/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
40 if (apply_event_and_update_pos(&rollback_event, thd, rli) !=
4767 SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK) {
4768 delete rollback_event;
4769 return true;
4770 }
4771
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 mysql_mutex_lock(&rli->data_lock);
4772
4773 40 return false;
4774 40 }
4775
4776 /**
4777 Top-level function for executing the next event in the relay log.
4778 This is called from the SQL thread.
4779
4780 This function reads the event from the relay log, executes it, and
4781 advances the relay log position. It also handles errors, etc.
4782
4783 This function may fail to apply the event for the following reasons:
4784
4785 - The position specified by the UNTIL condition of the START SLAVE
4786 command is reached.
4787
4788 - It was not possible to read the event from the log.
4789
4790 - The slave is killed.
4791
4792 - An error occurred when applying the event, and the event has been
4793 tried slave_trans_retries times. If the event has been retried
4794 fewer times, 0 is returned.
4795
4796 - init_info or init_relay_log_pos failed. (These are called
4797 if a failure occurs when applying the event.)
4798
4799 - An error occurred when updating the binlog position.
4800
4801 @retval 0 The event was applied.
4802
4803 @retval 1 The event was not applied.
4804 */
4805 1872151 static int exec_relay_log_event(THD *thd, Relay_log_info *rli,
4806 Rpl_applier_reader *applier_reader,
4807 Log_event *in) {
4808
1/2
✓ Branch 0 taken 1872151 times.
✗ Branch 1 not taken.
1872151 DBUG_TRACE;
4809
4810 /*
4811 We acquire this mutex since we need it for all operations except
4812 event execution. But we will release it in places where we will
4813 wait for something for example inside of next_event().
4814 */
4815
1/2
✓ Branch 0 taken 1872151 times.
✗ Branch 1 not taken.
1872151 mysql_mutex_lock(&rli->data_lock);
4816
4817 1872151 Log_event *ev = nullptr;
4818 #ifndef NDEBUG
4819
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1872151 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1872151 times.
✗ Branch 5 not taken.
1872151 if (!abort_slave_event_count || rli->events_until_exit--)
4820 #endif
4821 1872151 ev = in;
4822
4823 1872151 Log_event **ptr_ev = nullptr;
4824 1872151 RLI_current_event_raii rli_c_ev(rli, ev);
4825
4826
2/2
✓ Branch 0 taken 1863734 times.
✓ Branch 1 taken 8417 times.
1872151 if (ev != nullptr) {
4827 /*
4828 To avoid assigned event groups exceeding rli->checkpoint_group, it
4829 need force to compute checkpoint.
4830 */
4831 1863734 bool force = rli->rli_checkpoint_seqno >= rli->checkpoint_group;
4832
6/8
✓ Branch 0 taken 1863734 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1863734 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 68947 times.
✓ Branch 5 taken 1794787 times.
✓ Branch 6 taken 68947 times.
✓ Branch 7 taken 1794787 times.
1863734 if (force || rli->is_time_for_mta_checkpoint()) {
4833
1/2
✓ Branch 0 taken 68947 times.
✗ Branch 1 not taken.
68947 mysql_mutex_unlock(&rli->data_lock);
4834
2/4
✓ Branch 0 taken 68947 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 68947 times.
68947 if (mta_checkpoint_routine(rli, force)) {
4835 delete ev;
4836 return 1;
4837 }
4838
1/2
✓ Branch 0 taken 68947 times.
✗ Branch 1 not taken.
68947 mysql_mutex_lock(&rli->data_lock);
4839 }
4840 }
4841
4842 /*
4843 It should be checked after calling mta_checkpoint_routine(), because that
4844 function could be interrupted by kill while 'force' is true.
4845 */
4846
3/4
✓ Branch 0 taken 1872151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8452 times.
✓ Branch 3 taken 1863699 times.
1872151 if (sql_slave_killed(thd, rli)) {
4847
1/2
✓ Branch 0 taken 8452 times.
✗ Branch 1 not taken.
8452 mysql_mutex_unlock(&rli->data_lock);
4848
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 8410 times.
8452 delete ev;
4849
4850
9/18
✓ Branch 0 taken 8452 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8452 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8452 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8452 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 8452 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8452 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 8452 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 8452 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8452 times.
✗ Branch 17 not taken.
8452 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_ERROR_READING_RELAY_LOG_EVENTS,
4851 rli->get_for_channel_str(), "slave SQL thread was killed");
4852 8452 return 1;
4853 }
4854
4855
2/2
✓ Branch 0 taken 1863692 times.
✓ Branch 1 taken 7 times.
1863699 if (ev) {
4856
3/4
✓ Branch 0 taken 1863692 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 306826 times.
✓ Branch 3 taken 1556866 times.
1863692 if (rli->is_row_format_required()) {
4857 306826 bool info_error{false};
4858 306826 binary_log::Log_event_basic_info log_event_info;
4859
1/2
✓ Branch 0 taken 306826 times.
✗ Branch 1 not taken.
306826 std::tie(info_error, log_event_info) = extract_log_event_basic_info(ev);
4860
4861
2/4
✓ Branch 0 taken 306826 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 306826 times.
613652 if (info_error ||
4862
2/4
✓ Branch 0 taken 306826 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 306826 times.
306826 rli->transaction_parser.feed_event(log_event_info, true)) {
4863 /* purecov: begin inspected */
4864 LogErr(WARNING_LEVEL,
4865 ER_RPL_SLAVE_SQL_THREAD_DETECTED_UNEXPECTED_EVENT_SEQUENCE);
4866 /* purecov: end */
4867 }
4868
4869
6/8
✓ Branch 0 taken 306826 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 306826 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 306819 times.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 306819 times.
306826 if (info_error || rli->transaction_parser.check_row_logging_constraints(
4870 log_event_info)) {
4871
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 rli->report(
4872 ERROR_LEVEL,
4873 ER_RPL_SLAVE_APPLY_LOG_EVENT_FAILED_INVALID_NON_ROW_FORMAT,
4874 ER_THD(thd,
4875 ER_RPL_SLAVE_APPLY_LOG_EVENT_FAILED_INVALID_NON_ROW_FORMAT),
4876 7 rli->mi->get_channel());
4877 7 rli->abort_slave = true;
4878
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 mysql_mutex_unlock(&rli->data_lock);
4879
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 delete ev;
4880 7 return 1;
4881 }
4882 }
4883
4884 enum enum_slave_apply_event_and_update_pos_retval exec_res;
4885
4886 1863685 ptr_ev = &ev;
4887 /*
4888 Even if we don't execute this event, we keep the master timestamp,
4889 so that seconds behind master shows correct delta (there are events
4890 that are not replayed, so we keep falling behind).
4891
4892 If it is an artificial event, or a relay log event (IO thread generated
4893 event) or ev->when is set to 0, or a FD from master, or a heartbeat
4894 event with server_id '0' then we don't update the last_master_timestamp.
4895
4896 In case of parallel execution last_master_timestamp is only updated when
4897 a job is taken out of GAQ. Thus when last_master_timestamp is 0 (which
4898 indicates that GAQ is empty, all slave workers are waiting for events from
4899 the Coordinator), we need to initialize it with a timestamp from the first
4900 event to be executed in parallel.
4901 */
4902
7/8
✓ Branch 0 taken 1863685 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1861907 times.
✓ Branch 3 taken 1778 times.
✓ Branch 4 taken 186615 times.
✓ Branch 5 taken 1675292 times.
✓ Branch 6 taken 121120 times.
✓ Branch 7 taken 1742565 times.
2052078 if ((!rli->is_parallel_exec() || rli->last_master_timestamp == 0) &&
4903
6/6
✓ Branch 0 taken 178486 times.
✓ Branch 1 taken 9907 times.
✓ Branch 2 taken 133756 times.
✓ Branch 3 taken 44730 times.
✓ Branch 4 taken 127438 times.
✓ Branch 5 taken 6318 times.
322149 !(ev->is_artificial_event() || ev->is_relay_log_event() ||
4904 133756 ev->get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT ||
4905
2/2
✓ Branch 0 taken 121120 times.
✓ Branch 1 taken 6318 times.
127438 ev->server_id == 0)) {
4906 121120 rli->last_master_timestamp =
4907 121120 ev->common_header->when.tv_sec + (time_t)ev->exec_time;
4908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121120 times.
121120 assert(rli->last_master_timestamp >= 0);
4909 }
4910
4911
3/4
✓ Branch 0 taken 1863685 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 109 times.
✓ Branch 3 taken 1863576 times.
1863685 if (rli->is_until_satisfied_before_dispatching_event(ev)) {
4912 /*
4913 Setting abort_slave flag because we do not want additional message about
4914 error in query execution to be printed.
4915 */
4916 109 rli->abort_slave = true;
4917
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
109 mysql_mutex_unlock(&rli->data_lock);
4918
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
109 delete ev;
4919 109 return SLAVE_APPLY_EVENT_UNTIL_REACHED;
4920 }
4921
4922 {
4923 /**
4924 The following failure injecion works in cooperation
4925 with tests setting @@global.debug= 'd,incomplete_group_in_relay_log'.
4926 Xid or Commit events are not executed to force the slave sql read
4927 hanging if the relay log does not have any more events.
4928 */
4929
12/16
✓ Branch 0 taken 1863576 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 1863561 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 8 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 13 times.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
1863576 DBUG_EXECUTE_IF(
4930 "incomplete_group_in_relay_log",
4931 if ((ev->get_type_code() == binary_log::XID_EVENT) ||
4932 ((ev->get_type_code() == binary_log::QUERY_EVENT) &&
4933 strcmp("COMMIT", ((Query_log_event *)ev)->query) == 0)) {
4934 rli->abort_slave = 1;
4935 mysql_mutex_unlock(&rli->data_lock);
4936 delete ev;
4937 rli->inc_event_relay_log_pos();
4938 return 0;
4939 };);
4940 }
4941
4942 /*
4943 GTID protocol will put a FORMAT_DESCRIPTION_EVENT from the master with
4944 log_pos != 0 after each (re)connection if auto positioning is enabled.
4945 This means that the SQL thread might have already started to apply the
4946 current group but, as the IO thread had to reconnect, it left this
4947 group incomplete and will start it again from the beginning.
4948 So, before applying this FORMAT_DESCRIPTION_EVENT, we must let the
4949 worker roll back the current group and gracefully finish its work,
4950 before starting to apply the new (complete) copy of the group.
4951 */
4952 1863574 if (ev->get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT &&
4953
4/4
✓ Branch 0 taken 13492 times.
✓ Branch 1 taken 35736 times.
✓ Branch 2 taken 10967 times.
✓ Branch 3 taken 2525 times.
49228 ev->server_id != ::server_id && ev->common_header->log_pos != 0 &&
4954
9/10
✓ Branch 0 taken 49228 times.
✓ Branch 1 taken 1814346 times.
✓ Branch 2 taken 10967 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10939 times.
✓ Branch 5 taken 28 times.
✓ Branch 6 taken 40 times.
✓ Branch 7 taken 10899 times.
✓ Branch 8 taken 40 times.
✓ Branch 9 taken 1863534 times.
1912802 rli->is_parallel_exec() && rli->curr_group_seen_gtid) {
4955
2/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
40 if (coord_handle_partial_binlogged_transaction(rli, ev))
4956 /*
4957 In the case of an error, coord_handle_partial_binlogged_transaction
4958 will not try to get the rli->data_lock again.
4959 */
4960 return 1;
4961 }
4962
4963 /* ptr_ev can change to NULL indicating MTS coorinator passed to a Worker */
4964
1/2
✓ Branch 0 taken 1863364 times.
✗ Branch 1 not taken.
1863574 exec_res = apply_event_and_update_pos(ptr_ev, thd, rli);
4965 /*
4966 Note: the above call to apply_event_and_update_pos executes
4967 mysql_mutex_unlock(&rli->data_lock);
4968 */
4969
4970 /* For deferred events, the ptr_ev is set to NULL
4971 in Deferred_log_events::add() function.
4972 Hence deferred events won't be deleted here.
4973 They will be deleted in Deferred_log_events::rewind() function.
4974 */
4975
2/2
✓ Branch 0 taken 140112 times.
✓ Branch 1 taken 1723252 times.
1863364 if (*ptr_ev) {
4976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140112 times.
140112 assert(*ptr_ev == ev); // event remains to belong to Coordinator
4977
4978
6/8
✓ Branch 0 taken 140112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 140083 times.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
140112 DBUG_EXECUTE_IF("dbug.calculate_sbm_after_previous_gtid_log_event", {
4979 if (ev->get_type_code() == binary_log::PREVIOUS_GTIDS_LOG_EVENT) {
4980 rpl_replica_debug_point(DBUG_RPL_S_SBM_AFTER_PREVIOUS_GTID_EV, thd);
4981 }
4982 };);
4983
10/12
✓ Branch 0 taken 140112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 140061 times.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 30 times.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 15 times.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 45 times.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
140112 DBUG_EXECUTE_IF("dbug.calculate_sbm_after_fake_rotate_log_event", {
4984 if (ev->get_type_code() == binary_log::ROTATE_EVENT &&
4985 ev->is_artificial_event()) {
4986 rpl_replica_debug_point(DBUG_RPL_S_SBM_AFTER_FAKE_ROTATE_EV, thd);
4987 }
4988 };);
4989 /*
4990 Format_description_log_event should not be deleted because it will be
4991 used to read info about the relay log's format; it will be deleted when
4992 the SQL thread does not need it, i.e. when this thread terminates.
4993 ROWS_QUERY_LOG_EVENT is destroyed at the end of the current statement
4994 clean-up routine.
4995 */
4996
5/6
✓ Branch 0 taken 90884 times.
✓ Branch 1 taken 49228 times.
✓ Branch 2 taken 90884 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 90884 times.
✓ Branch 5 taken 49228 times.
230996 if (ev->get_type_code() != binary_log::FORMAT_DESCRIPTION_EVENT &&
4997 90884 ev->get_type_code() != binary_log::ROWS_QUERY_LOG_EVENT) {
4998
3/8
✓ Branch 0 taken 90884 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90884 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 90884 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
90884 DBUG_PRINT("info", ("Deleting the event after it has been executed"));
4999
1/2
✓ Branch 0 taken 90884 times.
✗ Branch 1 not taken.
90884 delete ev;
5000 /*
5001 Raii guard is explicitly instructed to invalidate
5002 otherwise bogus association of the execution context with the being
5003 destroyed above event.
5004 */
5005 90884 ev = rli->current_event = nullptr;
5006 }
5007 }
5008
5009 /*
5010 exec_res == SLAVE_APPLY_EVENT_AND_UPDATE_POS_UPDATE_POS_ERROR
5011 update_log_pos failed: this should not happen, so we
5012 don't retry.
5013 exec_res == SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPEND_JOB_ERROR
5014 append_item_to_jobs() failed, this happened because
5015 thread was killed while waiting for enqueue on worker.
5016 */
5017
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1863362 times.
1863364 if (exec_res >= SLAVE_APPLY_EVENT_AND_UPDATE_POS_UPDATE_POS_ERROR) {
5018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 delete ev;
5019 2 return 1;
5020 }
5021
5022
2/2
✓ Branch 0 taken 1766930 times.
✓ Branch 1 taken 96432 times.
1863362 if (slave_trans_retries) {
5023 1766930 int temp_err = 0;
5024 1766930 bool silent = false;
5025
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 if (exec_res && !is_mts_worker(thd) /* no reexecution in MTS mode */ &&
5026
7/8
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 1766804 times.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 107 times.
✓ Branch 6 taken 19 times.
✓ Branch 7 taken 1766911 times.
1767075 (temp_err = rli->has_temporary_error(thd, 0, &silent)) &&
5027
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 !thd->get_transaction()->cannot_safely_rollback(
5028 Transaction_ctx::SESSION)) {
5029 const char *errmsg;
5030 /*
5031 We were in a transaction which has been rolled back because of a
5032 temporary error;
5033 let's seek back to BEGIN log event and retry it all again.
5034 Note, if lock wait timeout (innodb_lock_wait_timeout exceeded)
5035 there is no rollback since 5.0.13 (ref: manual).
5036 We have to not only seek but also
5037 a) init_info(), to seek back to hot relay log's start for later
5038 (for when we will come back to this hot log after re-processing the
5039 possibly existing old logs where BEGIN is: applier_reader will
5040 then need the cache to be at position 0 (see comments at beginning of
5041 init_info()).
5042 b) init_relay_log_pos(), because the BEGIN may be an older relay log.
5043 */
5044
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1 times.
19 if (rli->trans_retries < slave_trans_retries) {
5045 /*
5046 The transactions has to be rolled back before
5047 load_mi_and_rli_from_repositories is called. Because
5048 load_mi_and_rli_from_repositories will starts a new
5049 transaction if master_info_repository is TABLE.
5050 */
5051
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 rli->cleanup_context(thd, true);
5052 /*
5053 Temporary error status is both unneeded and harmful for following
5054 open-and-lock slave system tables but store its number first for
5055 monitoring purposes.
5056 */
5057 18 uint temp_trans_errno = thd->get_stmt_da()->mysql_errno();
5058
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 thd->clear_error();
5059
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 applier_reader->close();
5060 /*
5061 We need to figure out if there is a test case that covers
5062 this part. \Alfranio.
5063 */
5064
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (load_mi_and_rli_from_repositories(rli->mi, false, SLAVE_SQL,
5065 false, true))
5066 LogErr(ERROR_LEVEL,
5067 ER_RPL_SLAVE_FAILED_TO_INIT_MASTER_INFO_STRUCTURE,
5068 rli->get_for_channel_str());
5069
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 else if (applier_reader->open(&errmsg))
5070 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_CANT_INIT_RELAY_LOG_POSITION,
5071 rli->get_for_channel_str(), errmsg);
5072 else {
5073 18 exec_res = SLAVE_APPLY_EVENT_RETRY;
5074 /* chance for concurrent connection to get more locks */
5075 18 slave_sleep(thd,
5076
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 min<ulong>(rli->trans_retries, MAX_SLAVE_RETRY_PAUSE),
5077 sql_slave_killed, rli);
5078
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 mysql_mutex_lock(&rli->data_lock); // because of SHOW STATUS
5079
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (!silent) {
5080 18 rli->trans_retries++;
5081
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 if (rli->is_processing_trx()) {
5082
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 rli->retried_processing(temp_trans_errno,
5083 ER_THD_NONCONST(thd, temp_trans_errno),
5084 rli->trans_retries);
5085 }
5086 }
5087 18 rli->retried_trans++;
5088
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 mysql_mutex_unlock(&rli->data_lock);
5089 #ifndef NDEBUG
5090
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 14 times.
18 if (rli->trans_retries == 2 || rli->trans_retries == 6)
5091
4/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 DBUG_EXECUTE_IF("rpl_ps_tables_worker_retry", {
5092 rpl_replica_debug_point(DBUG_RPL_S_PS_TABLE_WORKER_RETRY);
5093 };);
5094
5095 #endif
5096
3/8
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
18 DBUG_PRINT("info", ("Slave retries transaction "
5097 "rli->trans_retries: %lu",
5098 rli->trans_retries));
5099 }
5100 } else {
5101 1 thd->fatal_error();
5102
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
5103 "Slave SQL thread retried transaction %lu time(s) "
5104 "in vain, giving up. Consider raising the value of "
5105 "the replica_transaction_retries variable.",
5106 rli->trans_retries);
5107 }
5108
6/8
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 1766804 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 107 times.
✓ Branch 4 taken 1766804 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 45434 times.
✓ Branch 7 taken 1721476 times.
3533714 } else if ((exec_res && !temp_err) ||
5109
2/2
✓ Branch 0 taken 45327 times.
✓ Branch 1 taken 1721476 times.
1766803 (opt_using_transactions &&
5110 1766804 rli->get_group_relay_log_pos() ==
5111 1766803 rli->get_event_relay_log_pos())) {
5112 /*
5113 Only reset the retry counter if the entire group succeeded
5114 or failed with a non-transient error. On a successful
5115 event, the execution will proceed as usual; in the case of a
5116 non-transient error, the slave will stop with an error.
5117 */
5118 45434 rli->trans_retries = 0; // restart from fresh
5119
3/8
✓ Branch 0 taken 45434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45434 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 45434 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
45434 DBUG_PRINT("info", ("Resetting retry counter, rli->trans_retries: %lu",
5120 rli->trans_retries));
5121 }
5122 }
5123
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 1863217 times.
1863361 if (exec_res) {
5124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 delete ev;
5125 /* Raii object is explicitly updated 'cos this branch doesn't end func */
5126 144 rli->current_event = nullptr;
5127
3/4
✓ Branch 0 taken 1863218 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1221 times.
✓ Branch 3 taken 1861997 times.
1863217 } else if (rli->is_until_satisfied_after_dispatching_event()) {
5128
1/2
✓ Branch 0 taken 1221 times.
✗ Branch 1 not taken.
1221 mysql_mutex_lock(&rli->data_lock);
5129 1221 rli->abort_slave = true;
5130
1/2
✓ Branch 0 taken 1221 times.
✗ Branch 1 not taken.
1221 mysql_mutex_unlock(&rli->data_lock);
5131 1221 return SLAVE_APPLY_EVENT_UNTIL_REACHED;
5132 }
5133 1862141 return exec_res;
5134 }
5135
5136 /*
5137 It is impossible to read next event to finish the event group whenever a
5138 read event error happens. So MTS group status is set to MTS_KILLED_GROUP to
5139 force stop.
5140 */
5141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP)
5142 rli->mts_group_status = Relay_log_info::MTS_KILLED_GROUP;
5143
5144
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 mysql_mutex_unlock(&rli->data_lock);
5145
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 rli->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_READ_FAILURE,
5146 ER_THD(thd, ER_SLAVE_RELAY_LOG_READ_FAILURE),
5147 "\
5148 Could not parse relay log event entry. The possible reasons are: the master's \
5149 binary log is corrupted (you can check this by running 'mysqlbinlog' on the \
5150 binary log), the slave's relay log is corrupted (you can check this by running \
5151 'mysqlbinlog' on the relay log), a network problem, the server was unable to \
5152 fetch a keyring key required to open an encrypted relay log file, or a bug in \
5153 the master's or slave's MySQL code. If you want to check the master's binary \
5154 log or slave's relay log, you will be able to know their names by issuing \
5155 'SHOW SLAVE STATUS' on this slave.\
5156 ");
5157 7 return SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPLY_ERROR;
5158 1871941 }
5159
5160 1563641 static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info) {
5161
2/2
✓ Branch 0 taken 6751 times.
✓ Branch 1 taken 1556890 times.
1563641 if (io_slave_killed(thd, mi)) {
5162
2/2
✓ Branch 0 taken 6749 times.
✓ Branch 1 taken 2 times.
6751 if (info)
5163
8/16
✓ Branch 0 taken 6749 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6749 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6749 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6749 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6749 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6749 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6749 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 6749 times.
✗ Branch 15 not taken.
6749 LogErr(INFORMATION_LEVEL, ER_RPL_IO_THREAD_KILLED, info,
5164 mi->get_for_channel_str());
5165 6751 return true;
5166 }
5167 1556890 return false;
5168 }
5169
5170 /**
5171 @brief Try to reconnect slave IO thread.
5172
5173 @details Terminates current connection to master, sleeps for
5174 @c mi->connect_retry msecs and initiates new connection with
5175 @c safe_reconnect(). Variable pointed by @c retry_count is increased -
5176 if it exceeds @c mi->retry_count then connection is not re-established
5177 and function signals error.
5178
5179 Unless @c suppress_warnings is true, a warning is written to the
5180 server error log when reconnecting. The warning message, the
5181 messages used to report errors, and the thread stages, are taken
5182 from @c rm. In case @c mi->retry_count is exceeded, no messages are
5183 added to the log.
5184
5185 @param[in] thd Thread context.
5186 @param[in] mysql MySQL connection.
5187 @param[in] mi Master connection information.
5188 @param[in,out] retry_count Number of attempts to reconnect.
5189 @param[in] suppress_warnings true when a normal net read timeout
5190 has caused to reconnecting.
5191 @param[in] messages Error/warning messages and thread stage
5192 information. See class Reconnect_messages.
5193
5194 @retval 0 OK.
5195 @retval 1 There was an error.
5196 */
5197
5198 426 static int try_to_reconnect(THD *thd, MYSQL *mysql, Master_info *mi,
5199 uint *retry_count, bool suppress_warnings,
5200 const Reconnect_messages &messages) {
5201 426 mi->slave_running = MYSQL_SLAVE_RUN_NOT_CONNECT;
5202 426 THD_STAGE_INFO(thd, messages.stage_waiting_to_reconnect);
5203
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 420 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 6 times.
445 DBUG_EXECUTE_IF("hang_in_stage_replica_waiting_to_reconnect", {
5204 while (!io_slave_killed(thd, mi)) my_sleep(100000); // 0.1 second
5205 });
5206 426 thd->clear_active_vio();
5207 426 end_server(mysql);
5208
2/2
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 274 times.
426 if ((*retry_count)++) {
5209
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 130 times.
152 if (*retry_count > mi->retry_count) return 1; // Don't retry forever
5210 130 slave_sleep(thd, mi->connect_retry, io_slave_killed, mi);
5211 }
5212
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 398 times.
404 if (check_io_slave_killed(thd, mi,
5213 messages.error_killed_while_waiting.c_str()))
5214 6 return 1;
5215 398 THD_STAGE_INFO(thd, messages.stage_reconnecting);
5216
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 392 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 6 times.
416 DBUG_EXECUTE_IF("hang_in_stage_replica_reconnecting", {
5217 while (!io_slave_killed(thd, mi)) my_sleep(100000); // 0.1 second
5218 });
5219
2/2
✓ Branch 0 taken 396 times.
✓ Branch 1 taken 2 times.
398 if (!suppress_warnings) {
5220 char llbuff[22];
5221 /*
5222 Raise a warining during registering on master/requesting dump.
5223 Log a message reading event.
5224 */
5225
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 329 times.
396 if (messages.triggering_command.length()) {
5226 char buf[256];
5227
1/2
✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
67 snprintf(buf, sizeof(buf), messages.triggering_error.c_str(),
5228 mi->get_io_rpl_log_name(),
5229 67 llstr(mi->get_master_log_pos(), llbuff));
5230
5231
2/4
✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
✗ Branch 3 not taken.
67 mi->report(WARNING_LEVEL, ER_SLAVE_MASTER_COM_FAILURE,
5232 ER_THD(thd, ER_SLAVE_MASTER_COM_FAILURE),
5233 messages.triggering_command.c_str(), buf);
5234 } else {
5235
10/20
✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 329 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 329 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 329 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 329 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 329 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 329 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 329 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 329 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 329 times.
✗ Branch 19 not taken.
329 LogErr(INFORMATION_LEVEL, ER_SLAVE_RECONNECT_FAILED,
5236 mi->get_io_rpl_log_name(), llstr(mi->get_master_log_pos(), llbuff),
5237 mi->get_for_channel_str());
5238 }
5239 }
5240
8/14
✓ Branch 0 taken 398 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 332 times.
✓ Branch 3 taken 66 times.
✓ Branch 4 taken 332 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 332 times.
✓ Branch 8 taken 398 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 66 times.
✓ Branch 11 taken 332 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
398 if (safe_reconnect(thd, mysql, mi, true) || io_slave_killed(thd, mi)) {
5241
7/14
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 66 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 66 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 66 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 66 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 66 times.
✗ Branch 13 not taken.
66 LogErr(INFORMATION_LEVEL, ER_SLAVE_KILLED_AFTER_RECONNECT);
5242 66 return 1;
5243 }
5244 332 return 0;
5245 }
5246
5247 /**
5248 Slave IO thread entry point.
5249
5250 @param arg Pointer to Master_info struct that holds information for
5251 the IO thread.
5252
5253 @return Always 0.
5254 */
5255 7414 extern "C" void *handle_slave_io(void *arg) {
5256 7414 THD *thd{nullptr}; // needs to be first for thread_stack
5257 7414 bool thd_added{false};
5258 MYSQL *mysql;
5259 7414 Master_info *mi = (Master_info *)arg;
5260 7414 Relay_log_info *rli = mi->rli;
5261 char llbuff[22];
5262 uint retry_count;
5263 bool suppress_warnings;
5264 int ret;
5265 7414 Global_THD_manager *thd_manager = Global_THD_manager::get_instance();
5266 // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
5267
1/2
✓ Branch 0 taken 7414 times.
✗ Branch 1 not taken.
7414 my_thread_init();
5268 {
5269
1/2
✓ Branch 0 taken 7414 times.
✗ Branch 1 not taken.
7414 DBUG_TRACE;
5270
5271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7414 times.
7414 assert(mi->inited);
5272 7414 mysql = nullptr;
5273
5274
1/2
✓ Branch 0 taken 7414 times.
✗ Branch 1 not taken.
7414 mysql_mutex_lock(&mi->run_lock);
5275
5276 /* Inform waiting threads that slave has started */
5277 7414 mi->slave_run_id++;
5278
5279 #ifndef NDEBUG
5280 7414 mi->events_until_exit = disconnect_slave_event_count;
5281 #endif
5282
5283
2/4
✓ Branch 0 taken 7414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7414 times.
✗ Branch 3 not taken.
7414 thd = new THD; // note that constructor of THD uses DBUG_ !
5284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7414 times.
7414 THD_CHECK_SENTRY(thd);
5285 7414 mi->info_thd = thd;
5286
5287 #ifdef HAVE_PSI_THREAD_INTERFACE
5288 // save the instrumentation for IO thread in mi->info_thd
5289
1/2
✓ Branch 0 taken 7414 times.
✗ Branch 1 not taken.
7414 struct PSI_thread *psi = PSI_THREAD_CALL(get_thread)();
5290
1/2
✓ Branch 0 taken 7414 times.
✗ Branch 1 not taken.
7414 thd_set_psi(mi->info_thd, psi);
5291 #endif
5292
1/2
✓ Branch 0 taken 7414 times.
✗ Branch 1 not taken.
7414 mysql_thread_set_psi_THD(thd);
5293
5294 7414 thd->thread_stack = (char *)&thd; // remember where our stack is
5295
1/2
✓ Branch 0 taken 7414 times.
✗ Branch 1 not taken.
7414 mi->clear_error();
5296 7414 mi->slave_running = 1;
5297
3/4
✓ Branch 0 taken 7414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 7408 times.
7414 if (init_replica_thread(thd, SLAVE_THD_IO)) {
5298
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 mysql_cond_broadcast(&mi->start_cond);
5299
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 mysql_mutex_unlock(&mi->run_lock);
5300
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5301 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5302 "Failed during slave I/O thread initialization ");
5303 6 goto err;
5304 }
5305
5306
1/2
✓ Branch 0 taken 7408 times.
✗ Branch 1 not taken.
7408 thd_manager->add_thd(thd);
5307 7408 thd_added = true;
5308
5309 7408 mi->abort_slave = false;
5310
1/2
✓ Branch 0 taken 7408 times.
✗ Branch 1 not taken.
7408 mysql_mutex_unlock(&mi->run_lock);
5311
1/2
✓ Branch 0 taken 7408 times.
✗ Branch 1 not taken.
7408 mysql_cond_broadcast(&mi->start_cond);
5312
5313 7482 connect_init:
5314
3/10
✓ Branch 0 taken 7482 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7482 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7482 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
7482 DBUG_PRINT("master_info",
5315 ("log_file_name: '%s' position: %s", mi->get_master_log_name(),
5316 llstr(mi->get_master_log_pos(), llbuff)));
5317
5318 /* This must be called before run any binlog_relay_io hooks */
5319 7482 RPL_MASTER_INFO = mi;
5320
5321
6/8
✓ Branch 0 taken 7482 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5789 times.
✓ Branch 3 taken 1693 times.
✓ Branch 4 taken 1693 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 7470 times.
7482 if (RUN_HOOK(binlog_relay_io, thread_start, (thd, mi))) {
5322
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5323 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5324 "Failed to run 'thread_start' hook");
5325 12 goto err;
5326 }
5327
5328 7470 retry_count = 0;
5329
2/4
✓ Branch 0 taken 7470 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7470 times.
7470 if (!(mi->mysql = mysql = mysql_init(nullptr))) {
5330 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5331 ER_THD(thd, ER_SLAVE_FATAL_ERROR), "error in mysql_init()");
5332 goto err;
5333 }
5334
5335
1/2
✓ Branch 0 taken 7470 times.
✗ Branch 1 not taken.
7470 THD_STAGE_INFO(thd, stage_connecting_to_source);
5336
5337
3/4
✓ Branch 0 taken 7470 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7282 times.
✓ Branch 3 taken 188 times.
7470 if (!safe_connect(thd, mysql, mi)) {
5338
10/20
✓ Branch 0 taken 7282 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7282 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7282 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7282 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7282 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7282 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 7282 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 7282 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 7282 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 7282 times.
✗ Branch 19 not taken.
7282 LogErr(SYSTEM_LEVEL, ER_RPL_SLAVE_CONNECTED_TO_MASTER_REPLICATION_STARTED,
5339 mi->get_for_channel_str(), mi->get_user(), mi->host, mi->port,
5340 mi->get_io_rpl_log_name(),
5341 llstr(mi->get_master_log_pos(), llbuff));
5342 } else {
5343
9/18
✓ Branch 0 taken 188 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 188 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 188 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 188 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 188 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 188 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 188 times.
✗ Branch 17 not taken.
188 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_IO_THREAD_KILLED,
5344 mi->get_for_channel_str());
5345 188 goto err;
5346 }
5347
5348 7614 connected:
5349
5350 /*
5351 When using auto positioning, the slave IO thread will always start reading
5352 a transaction from the beginning of the transaction (transaction's first
5353 event). So, we have to reset the transaction boundary parser after
5354 (re)connecting.
5355 If not using auto positioning, the Relay_log_info::rli_init_info() took
5356 care of putting the mi->transaction_parser in the correct state when
5357 initializing Received_gtid_set from relay log during slave server starts,
5358 as the IO thread might had stopped in the middle of a transaction.
5359 */
5360
2/2
✓ Branch 0 taken 2325 times.
✓ Branch 1 taken 5289 times.
7614 if (mi->is_auto_position()) {
5361
1/2
✓ Branch 0 taken 2325 times.
✗ Branch 1 not taken.
2325 mi->transaction_parser.reset();
5362
1/2
✓ Branch 0 taken 2325 times.
✗ Branch 1 not taken.
2325 mi->clear_queueing_trx(true /* need_lock*/);
5363 }
5364
5365 7614 mi->reset_network_error();
5366
5367
4/6
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7611 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
7614 DBUG_EXECUTE_IF("dbug.before_get_running_status_yes", {
5368 rpl_replica_debug_point(DBUG_RPL_S_BEFORE_RUNNING_STATUS, thd);
5369 };);
5370
3/4
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7612 times.
7614 DBUG_EXECUTE_IF("dbug.calculate_sbm_after_previous_gtid_log_event", {
5371 /* Fake that thread started 3 minutes ago */
5372 thd->start_time.tv_sec -= 180;
5373 };);
5374
3/4
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7611 times.
7614 DBUG_EXECUTE_IF("dbug.calculate_sbm_after_fake_rotate_log_event", {
5375 /* Fake that thread started 3 minutes ago */
5376 thd->start_time.tv_sec -= 180;
5377 };);
5378
1/2
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
7614 mysql_mutex_lock(&mi->run_lock);
5379 7614 mi->slave_running = MYSQL_SLAVE_RUN_CONNECT;
5380
1/2
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
7614 mysql_mutex_unlock(&mi->run_lock);
5381
5382
1/2
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
7614 THD_STAGE_INFO(thd, stage_checking_source_version);
5383
1/2
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
7614 ret = get_master_version_and_clock(mysql, mi);
5384
3/4
✓ Branch 0 taken 7550 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 7550 times.
✗ Branch 3 not taken.
7614 if (!ret) ret = get_master_uuid(mysql, mi);
5385
3/4
✓ Branch 0 taken 7548 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 7548 times.
✗ Branch 3 not taken.
7614 if (!ret) ret = io_thread_init_commands(mysql, mi);
5386
5387
6/6
✓ Branch 0 taken 7548 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 153 times.
✓ Branch 3 taken 7395 times.
✓ Branch 4 taken 153 times.
✓ Branch 5 taken 7461 times.
7614 if (!ret && mi->is_source_connection_auto_failover()) {
5388
1/2
✓ Branch 0 taken 153 times.
✗ Branch 1 not taken.
153 ret = Async_conn_failover_manager::get_source_quorum_status(mysql, mi);
5389 }
5390
5391
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 7526 times.
7614 if (ret == 1) /* Fatal error */
5392 88 goto err;
5393
5394
7/8
✓ Branch 0 taken 7513 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 7513 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 7509 times.
✓ Branch 6 taken 17 times.
✓ Branch 7 taken 7509 times.
7526 if (ret == 2 || DBUG_EVALUATE_IF(
5395 "simulate_reconnect_after_failed_registration", 1, 0)) {
5396
3/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 12 times.
17 if (check_io_slave_killed(
5397 mi->info_thd, mi,
5398 "Slave I/O thread killed "
5399 "while calling get_master_version_and_clock(...)"))
5400 5 goto err;
5401 12 suppress_warnings = false;
5402 /* Try to reconnect because the error was caused by a transient network
5403 * problem */
5404
3/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 8 times.
12 if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings,
5405 reconnect_messages_after_failed_registration))
5406 4 goto err;
5407 8 goto connected;
5408 }
5409
5410 /*
5411 Register ourselves with the master.
5412 */
5413
1/2
✓ Branch 0 taken 7509 times.
✗ Branch 1 not taken.
7509 THD_STAGE_INFO(thd, stage_registering_replica_on_source);
5414
3/4
✓ Branch 0 taken 7509 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
✓ Branch 3 taken 7434 times.
7509 if (register_slave_on_master(mysql, mi, &suppress_warnings)) {
5415
3/4
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 1 times.
75 if (!check_io_slave_killed(thd, mi,
5416 "Slave I/O thread killed "
5417 "while registering slave on master")) {
5418
8/16
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 74 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 74 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 74 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 74 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 74 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 74 times.
✗ Branch 15 not taken.
74 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_IO_THREAD_CANT_REGISTER_ON_MASTER);
5419
3/4
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 55 times.
74 if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings,
5420 reconnect_messages_after_failed_registration))
5421 19 goto err;
5422 } else
5423 1 goto err;
5424 55 goto connected;
5425 }
5426
5427
3/8
✓ Branch 0 taken 7434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7434 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7434 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7434 DBUG_PRINT("info", ("Starting reading binary log from master"));
5428
3/4
✓ Branch 0 taken 7559 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7434 times.
✓ Branch 3 taken 125 times.
7559 while (!io_slave_killed(thd, mi)) {
5429 MYSQL_RPL rpl;
5430
5431
1/2
✓ Branch 0 taken 7434 times.
✗ Branch 1 not taken.
7434 THD_STAGE_INFO(thd, stage_requesting_binlog_dump);
5432
4/6
✓ Branch 0 taken 7434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7434 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 7430 times.
14868 if (request_dump(thd, mysql, &rpl, mi, &suppress_warnings) ||
5433
3/4
✓ Branch 0 taken 7434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 7430 times.
7434 DBUG_EVALUATE_IF("simulate_reconnect_after_failed_binlog_dump", 1,
5434 0)) {
5435
9/18
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
4 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_ERROR_REQUESTING_BINLOG_DUMP,
5436 mi->get_for_channel_str());
5437
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (check_io_slave_killed(thd, mi,
5438 "Slave I/O thread killed while "
5439
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 "requesting master dump") ||
5440
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings,
5441 reconnect_messages_after_failed_dump))
5442 6894 goto err;
5443 269 goto connected;
5444 }
5445 const char *event_buf;
5446
5447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7430 times.
7430 assert(mi->last_error().number == 0);
5448
3/4
✓ Branch 0 taken 1563329 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1563204 times.
✓ Branch 3 taken 125 times.
1563329 while (!io_slave_killed(thd, mi)) {
5449 ulong event_len;
5450 /*
5451 We say "waiting" because read_event() will wait if there's nothing to
5452 read. But if there's something to read, it will not wait. The
5453 important thing is to not confuse users by saying "reading" whereas
5454 we're in fact receiving nothing.
5455 */
5456
1/2
✓ Branch 0 taken 1563204 times.
✗ Branch 1 not taken.
1563204 THD_STAGE_INFO(thd, stage_waiting_for_source_to_send_event);
5457
1/2
✓ Branch 0 taken 1563058 times.
✗ Branch 1 not taken.
1563204 event_len = read_event(mysql, &rpl, mi, &suppress_warnings);
5458
5459
9/14
✓ Branch 0 taken 1563058 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1563053 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
1563058 DBUG_EXECUTE_IF(
5460 "relay_xid_trigger", if (event_len != packet_error) {
5461 const uchar *event_buf2 =
5462 static_cast<const uchar *>(mysql->net.read_pos + 1);
5463 Log_event_type event_type =
5464 static_cast<Log_event_type>(event_buf2[EVENT_TYPE_OFFSET]);
5465 if (event_type == binary_log::XID_EVENT) {
5466 static constexpr char act[] =
5467 "now signal relay_xid_reached wait_for resume";
5468 assert(
5469 !debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
5470 }
5471 });
5472
5473
3/4
✓ Branch 0 taken 1563058 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6737 times.
✓ Branch 3 taken 1556321 times.
1563058 if (check_io_slave_killed(thd, mi,
5474 "Slave I/O thread killed while "
5475 "reading event"))
5476 6890 goto err;
5477
5478
4/4
✓ Branch 0 taken 1555939 times.
✓ Branch 1 taken 382 times.
✓ Branch 2 taken 386 times.
✓ Branch 3 taken 1555935 times.
3112260 if (event_len == packet_error ||
5479
3/4
✓ Branch 0 taken 1555939 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1555935 times.
1555939 DBUG_EVALUATE_IF("simulate_reconnect_after_failed_event_read", 1,
5480 0)) {
5481
1/2
✓ Branch 0 taken 386 times.
✗ Branch 1 not taken.
386 uint mysql_error_number = mysql_errno(mysql);
5482
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 336 times.
386 switch (mysql_error_number) {
5483 3 case CR_NET_PACKET_TOO_LARGE:
5484
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(ERROR_LEVEL,
5485 ER_RPL_LOG_ENTRY_EXCEEDS_REPLICA_MAX_ALLOWED_PACKET,
5486 replica_max_allowed_packet);
5487
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mi->report(ERROR_LEVEL, ER_SERVER_NET_PACKET_TOO_LARGE, "%s",
5488 "Got a packet bigger than "
5489 "'replica_max_allowed_packet' bytes");
5490 3 goto err;
5491 47 case ER_MASTER_FATAL_ERROR_READING_BINLOG:
5492
3/6
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 47 times.
✗ Branch 5 not taken.
47 mi->report(ERROR_LEVEL,
5493 ER_SERVER_MASTER_FATAL_ERROR_READING_BINLOG,
5494 ER_THD(thd, ER_MASTER_FATAL_ERROR_READING_BINLOG),
5495 mysql_error_number, mysql_error(mysql));
5496 47 goto err;
5497 case ER_OUT_OF_RESOURCES:
5498 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_STOPPING_AS_MASTER_OOM);
5499 mi->report(ERROR_LEVEL, ER_SERVER_OUT_OF_RESOURCES, "%s",
5500 ER_THD(thd, ER_SERVER_OUT_OF_RESOURCES));
5501 goto err;
5502 }
5503
3/4
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
✓ Branch 3 taken 269 times.
336 if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings,
5504 reconnect_messages_after_failed_event_read))
5505 67 goto err;
5506 269 goto connected;
5507 } // if (event_len == packet_error)
5508
5509 1555935 retry_count = 0; // ok event, reset retry counter
5510
1/2
✓ Branch 0 taken 1555935 times.
✗ Branch 1 not taken.
1555935 THD_STAGE_INFO(thd, stage_queueing_source_event_to_the_relay_log);
5511 1555935 event_buf = (const char *)mysql->net.read_pos + 1;
5512
3/10
✓ Branch 0 taken 1555934 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1555934 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1555934 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1555935 DBUG_PRINT("info", ("IO thread received event of type %s",
5513 Log_event::get_type_str(
5514 (Log_event_type)event_buf[EVENT_TYPE_OFFSET])));
5515
5/8
✓ Branch 0 taken 1555934 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1185822 times.
✓ Branch 3 taken 370112 times.
✓ Branch 4 taken 370112 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1555934 times.
1555934 if (RUN_HOOK(binlog_relay_io, after_read_event,
5516 (thd, mi, (const char *)mysql->net.read_pos + 1, event_len,
5517 &event_buf, &event_len))) {
5518 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5519 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5520 "Failed to run 'after_read_event' hook");
5521 goto err;
5522 }
5523
5524 /* XXX: 'synced' should be updated by queue_event to indicate
5525 whether event has been synced to disk */
5526 1555934 bool synced = false;
5527 #ifndef NDEBUG
5528 1555934 bool was_in_trx = false;
5529
3/4
✓ Branch 0 taken 1555934 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1190657 times.
✓ Branch 3 taken 365277 times.
1555934 if (mi->is_queueing_trx()) {
5530 1190657 was_in_trx = true;
5531
4/6
✓ Branch 0 taken 1190657 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 1190647 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
1190657 DBUG_EXECUTE_IF("rpl_ps_tables_queue", {
5532 rpl_replica_debug_point(DBUG_RPL_S_PS_TABLE_QUEUE);
5533 };);
5534 }
5535 #endif
5536
1/2
✓ Branch 0 taken 1555935 times.
✗ Branch 1 not taken.
1555934 QUEUE_EVENT_RESULT queue_res = queue_event(mi, event_buf, event_len);
5537
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 1555902 times.
1555935 if (queue_res == QUEUE_EVENT_ERROR_QUEUING) {
5538
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
33 mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE,
5539 ER_THD(thd, ER_SLAVE_RELAY_LOG_WRITE_FAILURE),
5540 "could not queue event from master");
5541 33 goto err;
5542 }
5543 #ifndef NDEBUG
5544
7/8
✓ Branch 0 taken 1190651 times.
✓ Branch 1 taken 365251 times.
✓ Branch 2 taken 1190651 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 309943 times.
✓ Branch 5 taken 880708 times.
✓ Branch 6 taken 309943 times.
✓ Branch 7 taken 1245959 times.
1555902 if (was_in_trx && !mi->is_queueing_trx()) {
5545
4/6
✓ Branch 0 taken 309943 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 309933 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
309943 DBUG_EXECUTE_IF("rpl_ps_tables",
5546 { rpl_replica_debug_point(DBUG_RPL_S_PS_TABLES); };);
5547 }
5548 #endif
5549
5/8
✓ Branch 0 taken 1555902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1185790 times.
✓ Branch 3 taken 370112 times.
✓ Branch 4 taken 370112 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1555902 times.
1555902 if (RUN_HOOK(binlog_relay_io, after_queue_event,
5550 (thd, mi, event_buf, event_len, synced))) {
5551 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5552 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5553 "Failed to run 'after_queue_event' hook");
5554 goto err;
5555 }
5556
5557 /* The event was queued, but there was a failure flushing master info */
5558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1555902 times.
1555902 if (queue_res == QUEUE_EVENT_ERROR_FLUSHING_INFO) {
5559 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5560 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5561 "Failed to flush master info.");
5562 goto err;
5563 }
5564
5565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1555902 times.
1555902 assert(queue_res == QUEUE_EVENT_OK);
5566 /*
5567 Pause the IO thread execution and wait for
5568 'continue_after_queue_event' signal to continue IO thread
5569 execution.
5570 */
5571
4/6
✓ Branch 0 taken 1555902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
✓ Branch 3 taken 1555809 times.
✓ Branch 4 taken 93 times.
✗ Branch 5 not taken.
1555902 DBUG_EXECUTE_IF("pause_after_queue_event", {
5572 rpl_replica_debug_point(DBUG_RPL_S_PAUSE_AFTER_QUEUE_EV);
5573 };);
5574
5575 /*
5576 See if the relay logs take too much space.
5577 We don't lock mi->rli->log_space_lock here; this dirty read saves time
5578 and does not introduce any problem:
5579 - if mi->rli->ignore_log_space_limit is 1 but becomes 0 just after (so
5580 the clean value is 0), then we are reading only one more event as we
5581 should, and we'll block only at the next event. No big deal.
5582 - if mi->rli->ignore_log_space_limit is 0 but becomes 1 just after (so
5583 the clean value is 1), then we are going into
5584 wait_for_relay_log_space() for no reason, but this function will do a
5585 clean read, notice the clean value and exit immediately.
5586 */
5587 #ifndef NDEBUG
5588 {
5589 char llbuf1[22], llbuf2[22];
5590
3/12
✓ Branch 0 taken 1555902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1555902 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1555902 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1555902 DBUG_PRINT("info", ("log_space_limit=%s log_space_total=%s "
5591 "ignore_log_space_limit=%d",
5592 llstr(rli->log_space_limit, llbuf1),
5593 llstr(rli->log_space_total, llbuf2),
5594 (int)rli->ignore_log_space_limit));
5595 }
5596 #endif
5597
5598
3/4
✓ Branch 0 taken 1555901 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 1555892 times.
1555902 DBUG_EXECUTE_IF("rpl_set_relay_log_limits", {
5599 rli->log_space_limit = 10;
5600 rli->log_space_total = 20;
5601 };);
5602
5603 3111945 if (rli->log_space_limit &&
5604
6/6
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 1555758 times.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 56 times.
✓ Branch 4 taken 77 times.
✓ Branch 5 taken 1555824 times.
1555988 rli->log_space_limit < rli->log_space_total &&
5605
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 10 times.
87 !rli->ignore_log_space_limit)
5606
3/4
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 74 times.
77 if (wait_for_relay_log_space(rli)) {
5607
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(ERROR_LEVEL,
5608 ER_RPL_SLAVE_IO_THREAD_ABORTED_WAITING_FOR_RELAY_LOG_SPACE);
5609 3 goto err;
5610 }
5611
6/8
✓ Branch 0 taken 1555898 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 1555834 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 62 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
1555898 DBUG_EXECUTE_IF("flush_after_reading_user_var_event", {
5612 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::USER_VAR_EVENT)
5613 rpl_replica_debug_point(DBUG_RPL_S_FLUSH_AFTER_USERV_EV);
5614 });
5615
5/6
✓ Branch 0 taken 1555898 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 1555873 times.
✓ Branch 4 taken 22 times.
✓ Branch 5 taken 3 times.
1555898 DBUG_EXECUTE_IF(
5616 "stop_io_after_reading_gtid_log_event",
5617 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::GTID_LOG_EVENT)
5618 thd->killed = THD::KILLED_NO_VALUE;);
5619
5/6
✓ Branch 0 taken 1555898 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 1555846 times.
✓ Branch 4 taken 23 times.
✓ Branch 5 taken 29 times.
1555898 DBUG_EXECUTE_IF(
5620 "stop_io_after_reading_query_log_event",
5621 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::QUERY_EVENT)
5622 thd->killed = THD::KILLED_NO_VALUE;);
5623
5/6
✓ Branch 0 taken 1555898 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 1555834 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 52 times.
1555898 DBUG_EXECUTE_IF(
5624 "stop_io_after_reading_user_var_log_event",
5625 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::USER_VAR_EVENT)
5626 thd->killed = THD::KILLED_NO_VALUE;);
5627
5/6
✓ Branch 0 taken 1555898 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 1555865 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 22 times.
1555898 DBUG_EXECUTE_IF(
5628 "stop_io_after_reading_table_map_event",
5629 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::TABLE_MAP_EVENT)
5630 thd->killed = THD::KILLED_NO_VALUE;);
5631
5/6
✓ Branch 0 taken 1555898 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 1555827 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 60 times.
1555898 DBUG_EXECUTE_IF(
5632 "stop_io_after_reading_xid_log_event",
5633 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::XID_EVENT)
5634 thd->killed = THD::KILLED_NO_VALUE;);
5635
5/6
✓ Branch 0 taken 1555898 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 1555875 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 19 times.
1555898 DBUG_EXECUTE_IF(
5636 "stop_io_after_reading_write_rows_log_event",
5637 if (event_buf[EVENT_TYPE_OFFSET] == binary_log::WRITE_ROWS_EVENT)
5638 thd->killed = THD::KILLED_NO_VALUE;);
5639
5/6
✓ Branch 0 taken 1555898 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1555891 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 6 times.
1555898 DBUG_EXECUTE_IF(
5640 "stop_io_after_reading_unknown_event",
5641 /*
5642 * Cast to uchar, because of Percona's events
5643 * which have values > 128. This causes ENUM_END_EVENT to be > 128
5644 * but event_buf is char, so comparison does not work.
5645 */
5646 if (static_cast<uchar>(event_buf[EVENT_TYPE_OFFSET]) >=
5647 binary_log::ENUM_END_EVENT) thd->killed =
5648 THD::KILLED_NO_VALUE;);
5649
3/4
✓ Branch 0 taken 1555898 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1555885 times.
1555898 DBUG_EXECUTE_IF("stop_io_after_queuing_event",
5650 thd->killed = THD::KILLED_NO_VALUE;);
5651 /*
5652 After event is flushed to relay log file, memory used
5653 by thread's mem_root is not required any more.
5654 Hence adding ClearorReuse() to do the
5655 cleanup, otherwise a long running IO thread can
5656 cause OOM error.
5657 */
5658
1/2
✓ Branch 0 taken 1555899 times.
✗ Branch 1 not taken.
1555898 thd->mem_root->ClearForReuse();
5659 }
5660 }
5661
5662 // error = 0;
5663 125 err:
5664 /*
5665 If source_connection_auto_failover (async connection failover) is
5666 enabled, this server is not a Group Replication SECONDARY and
5667 Replica IO thread is not killed but failed due to network error, a
5668 connection to another source is attempted.
5669 */
5670 7342 if (mi->is_source_connection_auto_failover() &&
5671
7/8
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 7158 times.
✓ Branch 2 taken 184 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 182 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 97 times.
✓ Branch 7 taken 7245 times.
7524 !is_group_replication_member_secondary() &&
5672
3/4
✓ Branch 0 taken 182 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
✓ Branch 3 taken 97 times.
182 (!io_slave_killed(thd, mi) ||
5673
2/6
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 85 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
85 (!io_slave_killed(thd, mi) && mi->is_network_error()))) {
5674
4/6
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 94 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
97 DBUG_EXECUTE_IF("async_conn_failover_crash", DBUG_SUICIDE(););
5675
5676 /*
5677 Get the sender to connect to.
5678 If there is a STOP REPLICA ongoing for any channel, that is, a
5679 channel_map lock cannot be acquired by this channel IO thread,
5680 then this channel IO thread does skip the next sender selection.
5681 */
5682 Async_conn_failover_manager::enum_do_auto_conn_failover_error
5683 94 update_source_error =
5684 Async_conn_failover_manager::ACF_RETRIABLE_ERROR;
5685
2/4
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 94 times.
✗ Branch 3 not taken.
94 if (!channel_map.tryrdlock()) {
5686 update_source_error =
5687
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 Async_conn_failover_manager::do_auto_conn_failover(mi, false);
5688
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 channel_map.unlock();
5689 }
5690
5/8
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 76 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
94 DBUG_EXECUTE_IF("replica_retry_count_exceed", {
5691 if (Async_conn_failover_manager::ACF_NO_ERROR == update_source_error) {
5692 rpl_replica_debug_point(DBUG_RPL_S_RETRY_COUNT_EXCEED, thd);
5693 }
5694 });
5695
5696
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 6 times.
94 if (Async_conn_failover_manager::ACF_NO_SOURCES_ERROR !=
5697 update_source_error) {
5698 /* Wait before reconnect to avoid resources starvation. */
5699
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 my_sleep(1000000);
5700
5701 /* After waiting, recheck that a STOP REPLICA did not happen. */
5702
3/4
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 14 times.
88 if (!io_slave_killed(thd, mi)) {
5703 /* Reconnect. */
5704
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 1 times.
74 if (mysql) {
5705
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 thd->clear_active_vio();
5706
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 mysql_close(mysql);
5707 73 mi->mysql = nullptr;
5708 }
5709 74 goto connect_init;
5710 }
5711 }
5712 }
5713
5714 // print the current replication position
5715
10/20
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7265 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7265 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7265 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7265 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7265 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 7265 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 7265 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 7265 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 7265 times.
✗ Branch 19 not taken.
7265 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_IO_THREAD_EXITING,
5716 mi->get_for_channel_str(), mi->get_io_rpl_log_name(),
5717 llstr(mi->get_master_log_pos(), llbuff));
5718 /* At this point the I/O thread will not try to reconnect anymore. */
5719 7265 mi->atomic_is_stopping = true;
5720
4/6
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1660 times.
✓ Branch 3 taken 5605 times.
✓ Branch 4 taken 1660 times.
✗ Branch 5 not taken.
7265 (void)RUN_HOOK(binlog_relay_io, thread_stop, (thd, mi));
5721 /*
5722 Pause the IO thread and wait for 'continue_to_stop_io_thread'
5723 signal to continue to shutdown the IO thread.
5724 */
5725
2/6
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7265 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
7265 DBUG_EXECUTE_IF("pause_after_io_thread_stop_hook", {
5726 rpl_replica_debug_point(DBUG_RPL_S_PAUSE_AFTER_IO_STOP, thd);
5727 };);
5728
5729
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 thd->reset_query();
5730
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 thd->reset_db(NULL_CSTR);
5731
2/2
✓ Branch 0 taken 7248 times.
✓ Branch 1 taken 17 times.
7265 if (mysql) {
5732 /*
5733 Here we need to clear the active VIO before closing the
5734 connection with the master. The reason is that THD::awake()
5735 might be called from terminate_slave_thread() because somebody
5736 issued a STOP SLAVE. If that happends, the shutdown_active_vio()
5737 can be called in the middle of closing the VIO associated with
5738 the 'mysql' object, causing a crash.
5739 */
5740
1/2
✓ Branch 0 taken 7248 times.
✗ Branch 1 not taken.
7248 thd->clear_active_vio();
5741
1/2
✓ Branch 0 taken 7248 times.
✗ Branch 1 not taken.
7248 mysql_close(mysql);
5742 7248 mi->mysql = nullptr;
5743 }
5744
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 write_ignored_events_info_to_relay_log(thd, mi);
5745
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 THD_STAGE_INFO(thd, stage_waiting_for_replica_mutex_on_exit);
5746
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mysql_mutex_lock(&mi->run_lock);
5747 /*
5748 Clean information used to start slave in order to avoid
5749 security issues.
5750 */
5751
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mi->reset_start_info();
5752 /* Forget the relay log's format */
5753
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mysql_mutex_lock(rli->relay_log.get_log_lock());
5754
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mi->set_mi_description_event(nullptr);
5755
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mysql_mutex_unlock(rli->relay_log.get_log_lock());
5756
5757 // destructor will not free it, because net.vio is 0
5758
2/4
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7265 times.
✗ Branch 3 not taken.
7265 thd->get_protocol_classic()->end_net();
5759
5760
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 thd->release_resources();
5761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7265 times.
7265 THD_CHECK_SENTRY(thd);
5762
3/4
✓ Branch 0 taken 7259 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 7259 times.
✗ Branch 3 not taken.
7265 if (thd_added) thd_manager->remove_thd(thd);
5763
5764 7265 mi->abort_slave = false;
5765 7265 mi->slave_running = 0;
5766 7265 mi->atomic_is_stopping = false;
5767
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mysql_mutex_lock(&mi->info_thd_lock);
5768 7265 mi->info_thd = nullptr;
5769
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mysql_mutex_unlock(&mi->info_thd_lock);
5770
5771 /*
5772 The thd can only be destructed after indirect references
5773 through mi->info_thd are cleared: mi->info_thd= NULL.
5774
5775 For instance, user thread might be issuing show_slave_status
5776 and attempting to read mi->info_thd->proc_info().
5777 Therefore thd must only be deleted after info_thd is set
5778 to NULL.
5779 */
5780
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mysql_thread_set_psi_THD(nullptr);
5781
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 delete thd;
5782
5783 /*
5784 Note: the order of the two following calls (first broadcast, then unlock)
5785 is important. Otherwise a killer_thread can execute between the calls and
5786 delete the mi structure leading to a crash! (see BUG#25306 for details)
5787 */
5788
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mysql_cond_broadcast(&mi->stop_cond); // tell the world we are done
5789
4/6
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 7262 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
7265 DBUG_EXECUTE_IF("simulate_replica_delay_at_terminate_bug38694", sleep(5););
5790
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 mysql_mutex_unlock(&mi->run_lock);
5791 7265 }
5792
1/2
✓ Branch 0 taken 7265 times.
✗ Branch 1 not taken.
7265 my_thread_end();
5793 #if OPENSSL_VERSION_NUMBER < 0x10100000L
5794 ERR_remove_thread_state(0);
5795 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
5796 7265 my_thread_exit(nullptr);
5797 return (nullptr); // Avoid compiler warnings
5798 }
5799
5800 /*
5801 Check the temporary directory used by commands like
5802 LOAD DATA INFILE.
5803 */
5804 10418 static int check_temp_dir(char *tmp_file, const char *channel_name) {
5805 int fd;
5806 MY_DIR *dirp;
5807 char tmp_dir[FN_REFLEN];
5808 size_t tmp_dir_size;
5809
5810
1/2
✓ Branch 0 taken 10418 times.
✗ Branch 1 not taken.
10418 DBUG_TRACE;
5811
5812 /*
5813 Get the directory from the temporary file.
5814 */
5815
1/2
✓ Branch 0 taken 10418 times.
✗ Branch 1 not taken.
10418 dirname_part(tmp_dir, tmp_file, &tmp_dir_size);
5816
5817 /*
5818 Check if the directory exists.
5819 */
5820
3/4
✓ Branch 0 taken 10418 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 10415 times.
10418 if (!(dirp = my_dir(tmp_dir, MYF(MY_WME)))) return 1;
5821
1/2
✓ Branch 0 taken 10415 times.
✗ Branch 1 not taken.
10415 my_dirend(dirp);
5822
5823 /*
5824 Check permissions to create a file.
5825 */
5826 // append the server UUID to the temp file name.
5827 10415 constexpr uint size_of_tmp_file_name = 768;
5828 static_assert(size_of_tmp_file_name >= FN_REFLEN + TEMP_FILE_MAX_LEN, "");
5829
1/2
✓ Branch 0 taken 10415 times.
✗ Branch 1 not taken.
10415 char *unique_tmp_file_name = (char *)my_malloc(
5830 key_memory_rpl_replica_check_temp_dir, size_of_tmp_file_name, MYF(0));
5831 /*
5832 In the case of Multisource replication, the file create
5833 sometimes fail because of there is a race that a second SQL
5834 thread might create the same file and the creation fails.
5835 TO overcome this, we add a channel name to get a unique file name.
5836 */
5837
5838 /* @TODO: dangerous. Prevent this buffer flow */
5839 10415 snprintf(unique_tmp_file_name, size_of_tmp_file_name, "%s%s%s", tmp_file,
5840 channel_name, server_uuid);
5841
1/2
✓ Branch 0 taken 10415 times.
✗ Branch 1 not taken.
10415 if ((fd = mysql_file_create(key_file_misc, unique_tmp_file_name, CREATE_MODE,
5842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10415 times.
10415 O_WRONLY | O_EXCL | O_NOFOLLOW, MYF(MY_WME))) < 0)
5843 return 1;
5844
5845 /*
5846 Clean up.
5847 */
5848
1/2
✓ Branch 0 taken 10415 times.
✗ Branch 1 not taken.
10415 mysql_file_close(fd, MYF(0));
5849
5850
1/2
✓ Branch 0 taken 10415 times.
✗ Branch 1 not taken.
10415 mysql_file_delete(key_file_misc, unique_tmp_file_name, MYF(0));
5851
1/2
✓ Branch 0 taken 10415 times.
✗ Branch 1 not taken.
10415 my_free(unique_tmp_file_name);
5852 10415 return 0;
5853 10418 }
5854
5855 /*
5856 Worker thread for the parallel execution of the replication events.
5857 */
5858 extern "C" {
5859 41274 static void *handle_slave_worker(void *arg) {
5860 THD *thd; /* needs to be first for thread_stack */
5861 41274 bool thd_added = false;
5862 41274 int error = 0;
5863 41274 Slave_worker *w = (Slave_worker *)arg;
5864 41274 Relay_log_info *rli = w->c_rli;
5865 41274 ulong purge_cnt = 0;
5866 41274 ulonglong purge_size = 0;
5867 41274 struct slave_job_item _item, *job_item = &_item;
5868 41274 Global_THD_manager *thd_manager = Global_THD_manager::get_instance();
5869 #ifdef HAVE_PSI_THREAD_INTERFACE
5870 struct PSI_thread *psi;
5871 #endif
5872
5873
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 my_thread_init();
5874
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 DBUG_TRACE;
5875
5876
2/4
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41274 times.
✗ Branch 3 not taken.
41274 thd = new THD;
5877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41274 times.
41274 if (!thd) {
5878 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_CANT_INITIALIZE_SLAVE_WORKER,
5879 rli->get_for_channel_str());
5880 goto err;
5881 }
5882
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 mysql_mutex_lock(&w->info_thd_lock);
5883 41274 w->info_thd = thd;
5884
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 mysql_mutex_unlock(&w->info_thd_lock);
5885 41274 thd->thread_stack = (char *)&thd;
5886
5887 #ifdef HAVE_PSI_THREAD_INTERFACE
5888 // save the instrumentation for worker thread in w->info_thd
5889
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 psi = PSI_THREAD_CALL(get_thread)();
5890
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 thd_set_psi(w->info_thd, psi);
5891 #endif
5892
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 mysql_thread_set_psi_THD(thd);
5893
5894
2/4
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41274 times.
41274 if (init_replica_thread(thd, SLAVE_THD_WORKER)) {
5895 // todo make SQL thread killed
5896 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_CANT_INITIALIZE_SLAVE_WORKER,
5897 rli->get_for_channel_str());
5898 goto err;
5899 }
5900 41274 thd->rli_slave = w;
5901
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 thd->init_query_mem_roots();
5902
5903
3/4
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14420 times.
✓ Branch 3 taken 26854 times.
41274 if (channel_map.is_group_replication_channel_name(rli->get_channel())) {
5904
3/4
✓ Branch 0 taken 14420 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9175 times.
✓ Branch 3 taken 5245 times.
14420 if (channel_map.is_group_replication_channel_name(rli->get_channel(),
5905 true)) {
5906 9175 thd->rpl_thd_ctx.set_rpl_channel_type(GR_APPLIER_CHANNEL);
5907 } else {
5908 5245 thd->rpl_thd_ctx.set_rpl_channel_type(GR_RECOVERY_CHANNEL);
5909 }
5910 } else {
5911 26854 thd->rpl_thd_ctx.set_rpl_channel_type(RPL_STANDARD_CHANNEL);
5912 }
5913
5914 41274 w->set_filter(rli->rpl_filter);
5915
5916
3/4
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 776 times.
✓ Branch 3 taken 40498 times.
41274 if ((w->deferred_events_collecting = w->rpl_filter->is_on()))
5917
2/4
✓ Branch 0 taken 776 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 776 times.
✗ Branch 3 not taken.
776 w->deferred_events = new Deferred_log_events();
5918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41274 times.
41274 assert(thd->rli_slave->info_thd == thd);
5919
5920 /* Set applier thread InnoDB priority */
5921
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 set_thd_tx_priority(thd, rli->get_thd_tx_priority());
5922 /* Set write set related options */
5923
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 set_thd_write_set_options(thd, rli->get_ignore_write_set_memory_limit(),
5924 41274 rli->get_allow_drop_write_set());
5925
5926
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 thd->variables.require_row_format = rli->is_row_format_required();
5927
5928 41274 if (Relay_log_info::PK_CHECK_STREAM !=
5929
3/4
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 41206 times.
41274 rli->get_require_table_primary_key_check())
5930 68 thd->variables.sql_require_primary_key =
5931
1/2
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
68 (rli->get_require_table_primary_key_check() ==
5932 Relay_log_info::PK_CHECK_ON);
5933
2/4
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41274 times.
✗ Branch 3 not taken.
41274 w->set_require_table_primary_key_check(
5934 rli->get_require_table_primary_key_check());
5935
5936 // Replicas shall not create GIPKs if source tables have no PKs
5937 41274 thd->variables.sql_generate_invisible_primary_key = false;
5938
5939
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 thd_manager->add_thd(thd);
5940 41274 thd_added = true;
5941
5942
2/4
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41274 times.
41274 if (w->update_is_transactional()) {
5943 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5944 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5945 "Error checking if the worker repository is transactional.");
5946 goto err;
5947 }
5948
5949
2/2
✓ Branch 0 taken 40691 times.
✓ Branch 1 taken 583 times.
41274 if (rli->get_commit_order_manager() != nullptr)
5950
1/2
✓ Branch 0 taken 40691 times.
✗ Branch 1 not taken.
40691 rli->get_commit_order_manager()->init_worker_context(
5951 *w); // Initialize worker context within Commit_order_manager
5952
5953
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 mysql_mutex_lock(&w->jobs_lock);
5954 41274 w->running_status = Slave_worker::RUNNING;
5955
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 mysql_cond_signal(&w->jobs_cond);
5956
5957
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 mysql_mutex_unlock(&w->jobs_lock);
5958
5959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41274 times.
41274 assert(thd->is_slave_error == 0);
5960
5961 41274 w->stats_exec_time = w->stats_read_time = 0;
5962
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 set_timespec_nsec(&w->ts_exec[0], 0);
5963
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 set_timespec_nsec(&w->ts_exec[1], 0);
5964
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 set_timespec_nsec(&w->stats_begin, 0);
5965
5966 // No need to report anything, all error handling will be performed in the
5967 // slave SQL thread.
5968
4/6
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41274 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 41270 times.
✓ Branch 5 taken 4 times.
41274 if (!rli->check_privilege_checks_user())
5969
1/2
✓ Branch 0 taken 41270 times.
✗ Branch 1 not taken.
41270 rli->initialize_security_context(w->info_thd); // Worker security context
5970 // initialization with
5971 // `PRIVILEGE_CHECKS_USER`
5972
5973
2/2
✓ Branch 0 taken 367365 times.
✓ Branch 1 taken 39762 times.
407127 while (!error) {
5974
1/2
✓ Branch 0 taken 365853 times.
✗ Branch 1 not taken.
367365 error = slave_worker_exec_job_group(w, rli);
5975 }
5976
5977 /*
5978 Cleanup after an error requires clear_error() go first.
5979 Otherwise assert(!all) in binlog_rollback()
5980 */
5981
1/2
✓ Branch 0 taken 39708 times.
✗ Branch 1 not taken.
39762 thd->clear_error();
5982
1/2
✓ Branch 0 taken 39393 times.
✗ Branch 1 not taken.
39708 w->cleanup_context(thd, error);
5983
5984
1/2
✓ Branch 0 taken 39301 times.
✗ Branch 1 not taken.
39393 mysql_mutex_lock(&w->jobs_lock);
5985
5986
3/4
✓ Branch 0 taken 40721 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1825 times.
✓ Branch 3 taken 38896 times.
41126 while (w->jobs.de_queue(job_item)) {
5987 1825 purge_cnt++;
5988 1825 purge_size += job_item->data->common_header->data_written;
5989
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1825 times.
1825 assert(job_item->data);
5990
1/2
✓ Branch 0 taken 1825 times.
✗ Branch 1 not taken.
1825 delete job_item->data;
5991 }
5992
5993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39218 times.
38896 assert(w->jobs.get_length() == 0);
5994
5995
1/2
✓ Branch 0 taken 39645 times.
✗ Branch 1 not taken.
39218 mysql_mutex_unlock(&w->jobs_lock);
5996
5997
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39645 mysql_mutex_lock(&rli->pending_jobs_lock);
5998 39846 rli->pending_jobs -= purge_cnt;
5999 39846 rli->mts_pending_jobs_size -= purge_size;
6000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39846 times.
39846 assert(rli->mts_pending_jobs_size < rli->mts_pending_jobs_size_max);
6001
6002
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39846 mysql_mutex_unlock(&rli->pending_jobs_lock);
6003
6004 /*
6005 In MTS case cleanup_after_session() has be called explicitly.
6006 TODO: to make worker thd be deleted before Slave_worker instance.
6007 */
6008
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39846 if (thd->rli_slave) {
6009 39846 w->cleanup_after_session();
6010 39846 thd->rli_slave = nullptr;
6011 }
6012
1/2
✓ Branch 0 taken 39822 times.
✗ Branch 1 not taken.
39846 mysql_mutex_lock(&w->jobs_lock);
6013
6014 struct timespec stats_end;
6015
1/2
✓ Branch 0 taken 39816 times.
✗ Branch 1 not taken.
39822 set_timespec_nsec(&stats_end, 0);
6016
3/8
✓ Branch 0 taken 39746 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39758 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 39758 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
39816 DBUG_PRINT("info",
6017 ("Worker %lu statistics: "
6018 "events processed = %lu "
6019 "online time = %llu "
6020 "events exec time = %llu "
6021 "events read time = %llu "
6022 "hungry waits = %lu "
6023 "priv queue overfills = %llu ",
6024 w->id, w->events_done, diff_timespec(&stats_end, &w->stats_begin),
6025 w->stats_exec_time, w->stats_read_time, w->wq_empty_waits,
6026 w->jobs.waited_overfill));
6027
6028 39758 w->running_status = Slave_worker::NOT_RUNNING;
6029
6030
1/2
✓ Branch 0 taken 39772 times.
✗ Branch 1 not taken.
39758 mysql_mutex_lock(&w->info_thd_lock);
6031 /* We will delete the THD descriptior in next step.
6032 Before Slave_worker is deleted in slave_stop_workers() its value will be
6033 copied by copy_values_for_PFS including info_thd member.
6034 The member is used in table_replication_applier_status_by_worker::make_row()
6035 however only if Slave_worker::running status is Slave_worker::RUNNING, so we
6036 are safe here.
6037 Without setting below member to nullptr, we would copy stale pointer anyway,
6038 so it is safer to explicitly say that
6039 */
6040 39772 w->info_thd = nullptr;
6041
1/2
✓ Branch 0 taken 39831 times.
✗ Branch 1 not taken.
39772 mysql_mutex_unlock(&w->info_thd_lock);
6042
6043
1/2
✓ Branch 0 taken 39673 times.
✗ Branch 1 not taken.
39831 mysql_cond_signal(&w->jobs_cond); // famous last goodbye
6044
6045
1/2
✓ Branch 0 taken 39836 times.
✗ Branch 1 not taken.
39673 mysql_mutex_unlock(&w->jobs_lock);
6046
6047 39836 err:
6048
6049
2/2
✓ Branch 0 taken 39833 times.
✓ Branch 1 taken 3 times.
39836 if (thd) {
6050 /*
6051 The slave code is very bad. Notice that it is missing
6052 several clean up calls here. I've just added what was
6053 necessary to avoid valgrind errors.
6054
6055 /Alfranio
6056 */
6057
2/4
✓ Branch 0 taken 39406 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39670 times.
✗ Branch 3 not taken.
39833 thd->get_protocol_classic()->end_net();
6058
6059 /*
6060 to avoid close_temporary_tables() closing temp tables as those
6061 are Coordinator's burden.
6062 */
6063 39670 thd->system_thread = NON_SYSTEM_THREAD;
6064
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39670 thd->release_resources();
6065
6066
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39846 times.
39846 THD_CHECK_SENTRY(thd);
6067
2/4
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39843 times.
✗ Branch 3 not taken.
39846 if (thd_added) thd_manager->remove_thd(thd);
6068
1/2
✓ Branch 0 taken 39825 times.
✗ Branch 1 not taken.
39843 mysql_thread_set_psi_THD(nullptr);
6069
1/2
✓ Branch 0 taken 39826 times.
✗ Branch 1 not taken.
39825 delete thd;
6070 }
6071
6072
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39511 my_thread_end();
6073 #if OPENSSL_VERSION_NUMBER < 0x10100000L
6074 ERR_remove_thread_state(0);
6075 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
6076 39846 my_thread_exit(nullptr);
6077 return nullptr;
6078 39255 }
6079 } // extern "C"
6080
6081 /**
6082 Orders jobs by comparing relay log information.
6083 */
6084
6085 21192 int mts_event_coord_cmp(LOG_POS_COORD *id1, LOG_POS_COORD *id2) {
6086 21192 longlong filecmp = strcmp(id1->file_name, id2->file_name);
6087 21192 longlong poscmp = id1->pos - id2->pos;
6088 return (filecmp < 0
6089
2/2
✓ Branch 0 taken 4371 times.
✓ Branch 1 taken 16821 times.
25563 ? -1
6090
5/6
✓ Branch 0 taken 4371 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3405 times.
✓ Branch 3 taken 966 times.
✓ Branch 4 taken 229 times.
✓ Branch 5 taken 3176 times.
25563 : (filecmp > 0 ? 1 : (poscmp < 0 ? -1 : (poscmp > 0 ? 1 : 0))));
6091 }
6092
6093 7285 bool mts_recovery_groups(Relay_log_info *rli) {
6094 7285 Log_event *ev = nullptr;
6095 7285 bool is_error = false;
6096 7285 bool flag_group_seen_begin = false;
6097 7285 uint recovery_group_cnt = 0;
6098 7285 bool not_reached_commit = true;
6099
6100 // Value-initialization, to avoid compiler warnings on push_back.
6101 7285 Slave_job_group job_worker = Slave_job_group();
6102
6103 7285 LOG_INFO linfo;
6104 7285 my_off_t offset = 0;
6105 7285 MY_BITMAP *groups = &rli->recovery_groups;
6106
1/2
✓ Branch 0 taken 7285 times.
✗ Branch 1 not taken.
7285 THD *thd = current_thd;
6107
6108
1/2
✓ Branch 0 taken 7285 times.
✗ Branch 1 not taken.
7285 DBUG_TRACE;
6109
6110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7285 times.
7285 assert(rli->replica_parallel_workers == 0);
6111
6112 /*
6113 Although mts_recovery_groups() is reentrant it returns
6114 early if the previous invocation raised any bit in
6115 recovery_groups bitmap.
6116 */
6117
2/2
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 7140 times.
7285 if (rli->is_mts_recovery()) return false;
6118
6119 /*
6120 The process of relay log recovery for the multi threaded applier
6121 is focused on marking transactions as already executed so they are
6122 skipped when the SQL thread applies them.
6123 This is important as the position stored for the last executed relay log
6124 position may be behind what transactions workers already handled.
6125 When GTID_MODE=ON however we can use the old relay log position, even if
6126 stale as applied transactions will be skipped due to GTIDs auto skip
6127 feature.
6128 */
6129
8/10
✓ Branch 0 taken 7140 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1983 times.
✓ Branch 3 taken 5157 times.
✓ Branch 4 taken 1983 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1776 times.
✓ Branch 7 taken 207 times.
✓ Branch 8 taken 1776 times.
✓ Branch 9 taken 5364 times.
9123 if (global_gtid_mode.get() == Gtid_mode::ON && rli->mi &&
6130 1983 rli->mi->is_auto_position()) {
6131 1776 rli->mts_recovery_group_cnt = 0;
6132 1776 return false;
6133 }
6134
6135 /*
6136 Save relay log position to compare with worker's position.
6137 */
6138 5364 LOG_POS_COORD cp = {const_cast<char *>(rli->get_group_master_log_name()),
6139 5364 rli->get_group_master_log_pos()};
6140
6141 /*
6142 Gathers information on valuable workers and stores it in
6143 above_lwm_jobs in asc ordered by the master binlog coordinates.
6144 */
6145 5364 Prealloced_array<Slave_job_group, 16> above_lwm_jobs(PSI_NOT_INSTRUMENTED);
6146
1/2
✓ Branch 0 taken 5364 times.
✗ Branch 1 not taken.
5364 above_lwm_jobs.reserve(rli->recovery_parallel_workers);
6147
6148 /*
6149 When info tables are used and autocommit= 0 we force a new
6150 transaction start to avoid table access deadlocks when START SLAVE
6151 is executed after STOP SLAVE with MTS enabled.
6152 */
6153
3/4
✓ Branch 0 taken 5364 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5363 times.
5364 if (is_autocommit_off_and_infotables(thd))
6154
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (trans_begin(thd)) goto err;
6155
6156
2/2
✓ Branch 0 taken 20910 times.
✓ Branch 1 taken 5363 times.
26273 for (uint id = 0; id < rli->recovery_parallel_workers; id++) {
6157 Slave_worker *worker =
6158
1/2
✓ Branch 0 taken 20910 times.
✗ Branch 1 not taken.
20910 Rpl_info_factory::create_worker(opt_rli_repository_id, id, rli, true);
6159
6160
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20909 times.
20910 if (!worker) {
6161
2/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if (is_autocommit_off_and_infotables(thd)) trans_rollback(thd);
6162 1 goto err;
6163 }
6164
6165 LOG_POS_COORD w_last = {
6166 20909 const_cast<char *>(worker->get_group_master_log_name()),
6167 20909 worker->get_group_master_log_pos()};
6168
2/2
✓ Branch 0 taken 229 times.
✓ Branch 1 taken 20680 times.
20909 if (mts_event_coord_cmp(&w_last, &cp) > 0) {
6169 /*
6170 Inserts information into a dynamic array for further processing.
6171 The jobs/workers are ordered by the last checkpoint positions
6172 workers have seen.
6173 */
6174 229 job_worker.worker = worker;
6175 229 job_worker.checkpoint_log_pos = worker->checkpoint_master_log_pos;
6176 229 job_worker.checkpoint_log_name = worker->checkpoint_master_log_name;
6177
6178
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 above_lwm_jobs.push_back(job_worker);
6179 } else {
6180 /*
6181 Deletes the worker because its jobs are included in the latest
6182 checkpoint.
6183 */
6184
1/2
✓ Branch 0 taken 20680 times.
✗ Branch 1 not taken.
20680 delete worker;
6185 }
6186 }
6187
6188 /*
6189 When info tables are used and autocommit= 0 we force transaction
6190 commit to avoid table access deadlocks when START SLAVE is executed
6191 after STOP SLAVE with MTS enabled.
6192 */
6193
3/4
✓ Branch 0 taken 5363 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5362 times.
5363 if (is_autocommit_off_and_infotables(thd))
6194
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (trans_commit(thd)) goto err;
6195
6196 /*
6197 In what follows, the group Recovery Bitmap is constructed.
6198
6199 seek(lwm);
6200
6201 while(w= next(above_lwm_w))
6202 do
6203 read G
6204 if G == w->last_comm
6205 w.B << group_cnt++;
6206 RB |= w.B;
6207 break;
6208 else
6209 group_cnt++;
6210 while(!eof);
6211 continue;
6212 */
6213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5363 times.
5363 assert(!rli->recovery_groups_inited);
6214
6215
3/4
✓ Branch 0 taken 5363 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 218 times.
✓ Branch 3 taken 5145 times.
5363 if (!above_lwm_jobs.empty()) {
6216
1/2
✓ Branch 0 taken 218 times.
✗ Branch 1 not taken.
218 bitmap_init(groups, nullptr, MTS_MAX_BITS_IN_GROUP);
6217 218 rli->recovery_groups_inited = true;
6218 218 bitmap_clear_all(groups);
6219 }
6220 5363 rli->mts_recovery_group_cnt = 0;
6221
4/6
✓ Branch 0 taken 5363 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5592 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 229 times.
✓ Branch 5 taken 5363 times.
5592 for (Slave_job_group *jg = above_lwm_jobs.begin(); jg != above_lwm_jobs.end();
6222 ++jg) {
6223 229 Slave_worker *w = jg->worker;
6224 229 LOG_POS_COORD w_last = {const_cast<char *>(w->get_group_master_log_name()),
6225 229 w->get_group_master_log_pos()};
6226
6227
8/16
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 229 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 229 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 229 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 229 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 229 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 229 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 229 times.
✗ Branch 15 not taken.
229 LogErr(INFORMATION_LEVEL,
6228 ER_RPL_MTS_GROUP_RECOVERY_RELAY_LOG_INFO_FOR_WORKER, w->id,
6229 w->get_group_relay_log_name(), w->get_group_relay_log_pos(),
6230 w->get_group_master_log_name(), w->get_group_master_log_pos());
6231
6232 229 recovery_group_cnt = 0;
6233 229 not_reached_commit = true;
6234
2/4
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 229 times.
229 if (rli->relay_log.find_log_pos(&linfo, rli->get_group_relay_log_name(),
6235 true)) {
6236 LogErr(ERROR_LEVEL, ER_RPL_ERROR_LOOKING_FOR_LOG,
6237 rli->get_group_relay_log_name());
6238 goto err;
6239 }
6240 229 offset = rli->get_group_relay_log_pos();
6241
6242
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 Relaylog_file_reader relaylog_file_reader(opt_replica_sql_verify_checksum);
6243
6244
2/2
✓ Branch 0 taken 254 times.
✓ Branch 1 taken 229 times.
483 for (int checking = 0; not_reached_commit; checking++) {
6245
2/4
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 254 times.
254 if (relaylog_file_reader.open(linfo.log_file_name, offset)) {
6246 LogErr(ERROR_LEVEL, ER_BINLOG_FILE_OPEN_FAILED,
6247 relaylog_file_reader.get_error_str());
6248 goto err;
6249 }
6250
6251
4/4
✓ Branch 0 taken 1282 times.
✓ Branch 1 taken 229 times.
✓ Branch 2 taken 1257 times.
✓ Branch 3 taken 254 times.
2793 while (not_reached_commit &&
6252
3/4
✓ Branch 0 taken 1282 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1257 times.
✓ Branch 3 taken 25 times.
1282 (ev = relaylog_file_reader.read_event_object())) {
6253
2/4
✓ Branch 0 taken 1257 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1257 times.
1257 assert(ev->is_valid());
6254
6255
2/2
✓ Branch 0 taken 1182 times.
✓ Branch 1 taken 50 times.
2489 if (ev->get_type_code() == binary_log::ROTATE_EVENT ||
6256
2/2
✓ Branch 0 taken 1157 times.
✓ Branch 1 taken 25 times.
2414 ev->get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT ||
6257
5/6
✓ Branch 0 taken 1232 times.
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1157 times.
✓ Branch 4 taken 100 times.
✓ Branch 5 taken 1157 times.
3671 ev->get_type_code() == binary_log::PREVIOUS_GTIDS_LOG_EVENT ||
6258 1157 ev->get_type_code() == binary_log::START_5_7_ENCRYPTION_EVENT) {
6259
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 delete ev;
6260 100 ev = nullptr;
6261 100 continue;
6262 }
6263
6264
3/8
✓ Branch 0 taken 1157 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1157 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1157 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1157 DBUG_PRINT(
6265 "mts",
6266 ("Event Recoverying relay log info "
6267 "group_mster_log_name %s, event_master_log_pos %llu type code %u.",
6268 linfo.log_file_name, ev->common_header->log_pos,
6269 ev->get_type_code()));
6270
6271
3/4
✓ Branch 0 taken 1157 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 165 times.
✓ Branch 3 taken 992 times.
1157 if (ev->starts_group()) {
6272 165 flag_group_seen_begin = true;
6273
7/8
✓ Branch 0 taken 992 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 824 times.
✓ Branch 3 taken 168 times.
✓ Branch 4 taken 395 times.
✓ Branch 5 taken 429 times.
✓ Branch 6 taken 283 times.
✓ Branch 7 taken 709 times.
1555 } else if ((ev->ends_group() || !flag_group_seen_begin) &&
6274
2/2
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 280 times.
563 !is_gtid_event(ev)) {
6275 283 int ret = 0;
6276 LOG_POS_COORD ev_coord = {
6277 283 const_cast<char *>(rli->get_group_master_log_name()),
6278 283 ev->common_header->log_pos};
6279 283 flag_group_seen_begin = false;
6280 283 recovery_group_cnt++;
6281
6282
8/16
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 283 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 283 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 283 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 283 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 283 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 283 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 283 times.
✗ Branch 15 not taken.
283 LogErr(INFORMATION_LEVEL, ER_RPL_MTS_GROUP_RECOVERY_RELAY_LOG_INFO,
6283 rli->get_group_master_log_name_info(),
6284 ev->common_header->log_pos);
6285
2/2
✓ Branch 0 taken 229 times.
✓ Branch 1 taken 54 times.
283 if ((ret = mts_event_coord_cmp(&ev_coord, &w_last)) == 0) {
6286 #ifndef NDEBUG
6287
2/2
✓ Branch 0 taken 294 times.
✓ Branch 1 taken 229 times.
523 for (uint i = 0; i <= w->worker_checkpoint_seqno; i++) {
6288
2/2
✓ Branch 0 taken 239 times.
✓ Branch 1 taken 55 times.
294 if (bitmap_is_set(&w->group_executed, i))
6289
3/8
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 239 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 239 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
239 DBUG_PRINT("mts", ("Bit %u is set.", i));
6290 else
6291
3/8
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 55 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
55 DBUG_PRINT("mts", ("Bit %u is not set.", i));
6292 }
6293 #endif
6294
3/8
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 229 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 229 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
229 DBUG_PRINT("mts",
6295 ("Doing a shift ini(%lu) end(%lu).",
6296 (w->worker_checkpoint_seqno + 1) - recovery_group_cnt,
6297 w->worker_checkpoint_seqno));
6298
6299 229 for (uint i = (w->worker_checkpoint_seqno + 1) - recovery_group_cnt,
6300 229 j = 0;
6301
2/2
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 229 times.
512 i <= w->worker_checkpoint_seqno; i++, j++) {
6302
2/2
✓ Branch 0 taken 236 times.
✓ Branch 1 taken 47 times.
283 if (bitmap_is_set(&w->group_executed, i)) {
6303
3/8
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 236 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 236 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
236 DBUG_PRINT("mts", ("Setting bit %u.", j));
6304
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
236 bitmap_test_and_set(groups, j);
6305 }
6306 }
6307 229 not_reached_commit = false;
6308 } else
6309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 assert(ret < 0);
6310 }
6311
1/2
✓ Branch 0 taken 1157 times.
✗ Branch 1 not taken.
1157 delete ev;
6312 1157 ev = nullptr;
6313 }
6314
6315
1/2
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
254 relaylog_file_reader.close();
6316 254 offset = BIN_LOG_HEADER_SIZE;
6317
5/8
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 229 times.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 25 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 254 times.
254 if (not_reached_commit && rli->relay_log.find_next_log(&linfo, true)) {
6318 LogErr(ERROR_LEVEL, ER_RPL_CANT_FIND_FOLLOWUP_FILE,
6319 linfo.log_file_name);
6320 goto err;
6321 }
6322 }
6323
6324 229 rli->mts_recovery_group_cnt =
6325 229 (rli->mts_recovery_group_cnt < recovery_group_cnt
6326 229 ? recovery_group_cnt
6327 : rli->mts_recovery_group_cnt);
6328
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 }
6329
6330
3/4
✓ Branch 0 taken 218 times.
✓ Branch 1 taken 5145 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 218 times.
5363 assert(!rli->recovery_groups_inited ||
6331 rli->mts_recovery_group_cnt <= groups->n_bits);
6332
6333 5363 goto end;
6334 1 err:
6335 1 is_error = true;
6336 5364 end:
6337
6338
4/6
✓ Branch 0 taken 5364 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5593 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 229 times.
✓ Branch 5 taken 5364 times.
5593 for (Slave_job_group *jg = above_lwm_jobs.begin(); jg != above_lwm_jobs.end();
6339 ++jg) {
6340
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 delete jg->worker;
6341 }
6342
6343
3/4
✓ Branch 0 taken 5146 times.
✓ Branch 1 taken 218 times.
✓ Branch 2 taken 5146 times.
✗ Branch 3 not taken.
5364 if (rli->mts_recovery_group_cnt == 0) rli->clear_mts_recovery_groups();
6344
6345 5364 return is_error;
6346 7285 }
6347
6348 721446 bool mta_checkpoint_routine(Relay_log_info *rli, bool force) {
6349 ulong cnt;
6350 721446 bool error = false;
6351 721446 time_t ts = 0;
6352
6353
1/2
✓ Branch 0 taken 721446 times.
✗ Branch 1 not taken.
721446 DBUG_TRACE;
6354
6355 #ifndef NDEBUG
6356
2/4
✓ Branch 0 taken 721446 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 721446 times.
721446 if (DBUG_EVALUATE_IF("check_replica_debug_group", 1, 0)) {
6357 if (!rli->gaq->count_done(rli)) return false;
6358 }
6359
4/6
✓ Branch 0 taken 721446 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 721428 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
721446 DBUG_EXECUTE_IF("mta_checkpoint", {
6360 rpl_replica_debug_point(DBUG_RPL_S_MTS_CHECKPOINT_START, rli->info_thd);
6361 };);
6362 #endif
6363
6364 #ifndef NDEBUG
6365 /*
6366 rli->checkpoint_group can have two possible values due to
6367 two possible status of the last (being scheduled) group.
6368 */
6369 const bool precondition =
6370
2/4
✓ Branch 0 taken 721446 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 721446 times.
721446 !rli->gaq->full() ||
6371 ((rli->rli_checkpoint_seqno == rli->checkpoint_group - 1 &&
6372 (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP ||
6373 rli->mts_group_status == Relay_log_info::MTS_KILLED_GROUP)) ||
6374 rli->rli_checkpoint_seqno == rli->checkpoint_group);
6375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 721446 times.
721446 if (!precondition) {
6376 fprintf(stderr, "rli->gaq->full() = %d\n", rli->gaq->full());
6377 fprintf(stderr, "rli->rl_checkpoint_seqno = %u\n",
6378 rli->rli_checkpoint_seqno);
6379 fprintf(stderr, "rli->checkpoint_group = %u\n", rli->checkpoint_group);
6380 fprintf(stderr, "rli->mts_group_status = %d\n", rli->mts_group_status);
6381 assert(precondition);
6382 }
6383 #endif
6384
6385 do {
6386
4/6
✓ Branch 0 taken 12894229 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12893461 times.
✓ Branch 3 taken 768 times.
✓ Branch 4 taken 9957854 times.
✗ Branch 5 not taken.
12894229 if (!is_mts_db_partitioned(rli)) mysql_mutex_lock(&rli->mts_gaq_LOCK);
6387
6388
1/2
✓ Branch 0 taken 12894215 times.
✗ Branch 1 not taken.
9958622 cnt = rli->gaq->move_queue_head(&rli->workers);
6389
6390
4/6
✓ Branch 0 taken 12894215 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12893447 times.
✓ Branch 3 taken 768 times.
✓ Branch 4 taken 12893447 times.
✗ Branch 5 not taken.
12894215 if (!is_mts_db_partitioned(rli)) mysql_mutex_unlock(&rli->mts_gaq_LOCK);
6391 #ifndef NDEBUG
6392
3/6
✓ Branch 0 taken 12894214 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12894214 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12894214 times.
12894215 if (DBUG_EVALUATE_IF("check_replica_debug_group", 1, 0) &&
6393 cnt != opt_mta_checkpoint_period)
6394 LogErr(ERROR_LEVEL, ER_RPL_MTS_CHECKPOINT_PERIOD_DIFFERS_FROM_CNT);
6395 #endif
6396
5/6
✓ Branch 0 taken 12894208 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12749114 times.
✓ Branch 3 taken 135928 times.
✓ Branch 4 taken 12172960 times.
✓ Branch 5 taken 576154 times.
25779256 } while (!sql_slave_killed(rli->info_thd, rli) && cnt == 0 && force &&
6397
6/8
✓ Branch 0 taken 12885042 times.
✓ Branch 1 taken 9166 times.
✓ Branch 2 taken 12172960 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12172960 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12172783 times.
✓ Branch 7 taken 721248 times.
37952033 !DBUG_EVALUATE_IF("check_replica_debug_group", 1, 0) &&
6398
1/2
✓ Branch 0 taken 12172783 times.
✗ Branch 1 not taken.
12172960 (my_sleep(rli->mts_coordinator_basic_nap), 1));
6399 /*
6400 This checks how many consecutive jobs where processed.
6401 If this value is different than zero the checkpoint
6402 routine can proceed. Otherwise, there is nothing to be
6403 done.
6404 */
6405
2/2
✓ Branch 0 taken 583876 times.
✓ Branch 1 taken 137372 times.
721248 if (cnt == 0) goto end;
6406
6407 /*
6408 The workers have completed cnt jobs from the gaq. This means that we
6409 should increment C->jobs_done by cnt.
6410 */
6411
6/8
✓ Branch 0 taken 137372 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 137372 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 137237 times.
✓ Branch 5 taken 135 times.
✓ Branch 6 taken 137237 times.
✓ Branch 7 taken 135 times.
137372 if (!is_mts_worker(rli->info_thd) && !is_mts_db_partitioned(rli)) {
6412
3/8
✓ Branch 0 taken 137237 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 137237 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 137237 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
137237 DBUG_PRINT("info", ("jobs_done this itr=%ld", cnt));
6413 137237 static_cast<Mts_submode_logical_clock *>(rli->current_mts_submode)
6414 137237 ->jobs_done += cnt;
6415 }
6416
6417
1/2
✓ Branch 0 taken 137372 times.
✗ Branch 1 not taken.
137372 mysql_mutex_lock(&rli->data_lock);
6418
6419 /*
6420 "Coordinator::commit_positions"
6421
6422 rli->gaq->lwm has been updated in move_queue_head() and
6423 to contain all but rli->group_master_log_name which
6424 is altered solely by Coordinator at special checkpoints.
6425 */
6426 137372 rli->set_group_master_log_pos(rli->gaq->lwm.group_master_log_pos);
6427 137372 rli->set_group_relay_log_pos(rli->gaq->lwm.group_relay_log_pos);
6428
3/8
✓ Branch 0 taken 137372 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 137372 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 137372 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
137372 DBUG_PRINT(
6429 "mts",
6430 ("New checkpoint %llu %llu %s", rli->gaq->lwm.group_master_log_pos,
6431 rli->gaq->lwm.group_relay_log_pos, rli->gaq->lwm.group_relay_log_name));
6432
6433
1/2
✓ Branch 0 taken 137372 times.
✗ Branch 1 not taken.
137372 if (rli->gaq->lwm.group_relay_log_name[0] != 0)
6434
1/2
✓ Branch 0 taken 137372 times.
✗ Branch 1 not taken.
137372 rli->set_group_relay_log_name(rli->gaq->lwm.group_relay_log_name);
6435
6436 /*
6437 todo: uncomment notifies when UNTIL will be supported
6438
6439 rli->notify_group_master_log_name_update();
6440 rli->notify_group_relay_log_name_update();
6441
6442 Todo: optimize with if (wait_flag) broadcast
6443 waiter: set wait_flag; waits....; drops wait_flag;
6444 */
6445
6446
1/2
✓ Branch 0 taken 137372 times.
✗ Branch 1 not taken.
137372 error = rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT);
6447
6448
1/2
✓ Branch 0 taken 137372 times.
✗ Branch 1 not taken.
137372 mysql_cond_broadcast(&rli->data_cond);
6449
1/2
✓ Branch 0 taken 137372 times.
✗ Branch 1 not taken.
137372 mysql_mutex_unlock(&rli->data_lock);
6450
6451 /*
6452 We need to ensure that this is never called at this point when
6453 cnt is zero. This value means that the checkpoint information
6454 will be completely reset.
6455 */
6456
6457 /*
6458 Update the rli->last_master_timestamp for reporting correct
6459 Seconds_behind_master.
6460
6461 If GAQ is empty, set it to zero.
6462 Else, update it with the timestamp of the first job of the Slave_job_queue
6463 which was assigned in the Log_event::get_slave_worker() function.
6464 */
6465
1/2
✓ Branch 0 taken 137372 times.
✗ Branch 1 not taken.
137372 ts = rli->gaq->empty()
6466
2/2
✓ Branch 0 taken 59418 times.
✓ Branch 1 taken 77954 times.
137372 ? 0
6467
1/2
✓ Branch 0 taken 77954 times.
✗ Branch 1 not taken.
77954 : reinterpret_cast<Slave_job_group *>(rli->gaq->head_queue())->ts;
6468
1/2
✓ Branch 0 taken 137372 times.
✗ Branch 1 not taken.
137372 rli->reset_notified_checkpoint(cnt, ts, true);
6469 /* end-of "Coordinator::commit_positions" */
6470
6471 721248 end:
6472
3/4
✓ Branch 0 taken 721248 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 721233 times.
721248 error = error || rli->info_thd->killed != THD::NOT_KILLED;
6473 #ifndef NDEBUG
6474
2/6
✓ Branch 0 taken 721248 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 721248 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
721248 if (DBUG_EVALUATE_IF("check_replica_debug_group", 1, 0)) DBUG_SUICIDE();
6475
4/6
✓ Branch 0 taken 721248 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 721228 times.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
721248 DBUG_EXECUTE_IF("mta_checkpoint", {
6476 rpl_replica_debug_point(DBUG_RPL_S_MTS_CHECKPOINT_END, rli->info_thd);
6477 };);
6478 #endif
6479
1/2
✓ Branch 0 taken 721248 times.
✗ Branch 1 not taken.
721248 set_timespec_nsec(&rli->last_clock, 0);
6480
6481 721248 return error;
6482 721248 }
6483
6484 /**
6485 Instantiation of a Slave_worker and forking out a single Worker thread.
6486
6487 @param rli Coordinator's Relay_log_info pointer
6488 @param i identifier of the Worker
6489
6490 @return 0 suppress or 1 if fails
6491 */
6492 41276 static int slave_start_single_worker(Relay_log_info *rli, ulong i) {
6493 41276 int error = 0;
6494 41276 my_thread_handle th;
6495 41276 Slave_worker *w = nullptr;
6496
6497 41276 mysql_mutex_assert_owner(&rli->run_lock);
6498
6499
2/4
✓ Branch 0 taken 41276 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41276 times.
41276 if (!(w = Rpl_info_factory::create_worker(opt_rli_repository_id, i, rli,
6500 false))) {
6501 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_WORKER_THREAD_CREATION_FAILED,
6502 rli->get_for_channel_str());
6503 error = 1;
6504 goto err;
6505 }
6506
6507
3/4
✓ Branch 0 taken 41276 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 41275 times.
41276 if (w->init_worker(rli, i)) {
6508
9/18
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
1 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_WORKER_THREAD_CREATION_FAILED,
6509 rli->get_for_channel_str());
6510 1 error = 1;
6511 1 goto err;
6512 }
6513
6514 // We assume that workers are added in sequential order here.
6515
2/4
✓ Branch 0 taken 41275 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41275 times.
41275 assert(i == rli->workers.size());
6516
3/6
✓ Branch 0 taken 41275 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41275 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 41275 times.
✗ Branch 5 not taken.
41275 if (i >= rli->workers.size()) rli->workers.resize(i + 1);
6517
1/2
✓ Branch 0 taken 41275 times.
✗ Branch 1 not taken.
41275 rli->workers[i] = w;
6518
6519
9/10
✓ Branch 0 taken 41275 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 41273 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 41274 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 41274 times.
82549 if (DBUG_EVALUATE_IF("mta_worker_thread_fails", i == 1, 0) ||
6520
2/4
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41274 times.
41274 (error = mysql_thread_create(key_thread_replica_worker, &th,
6521 &connection_attrib, handle_slave_worker,
6522 (void *)w))) {
6523
9/18
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
1 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_WORKER_THREAD_CREATION_FAILED_WITH_ERRNO,
6524 rli->get_for_channel_str(), error);
6525 1 error = 1;
6526 1 goto err;
6527 }
6528
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 mysql_mutex_lock(&w->jobs_lock);
6529
2/2
✓ Branch 0 taken 41143 times.
✓ Branch 1 taken 131 times.
41274 if (w->running_status == Slave_worker::NOT_RUNNING)
6530
1/2
✓ Branch 0 taken 41143 times.
✗ Branch 1 not taken.
41143 mysql_cond_wait(&w->jobs_cond, &w->jobs_lock);
6531
1/2
✓ Branch 0 taken 41274 times.
✗ Branch 1 not taken.
41274 mysql_mutex_unlock(&w->jobs_lock);
6532
6533 41276 err:
6534
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 41274 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
41276 if (error && w) {
6535 // Free the current submode object
6536
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 delete w->current_mts_submode;
6537 2 w->current_mts_submode = nullptr;
6538
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 delete w;
6539 /*
6540 Any failure after array inserted must follow with deletion
6541 of just created item.
6542 */
6543
4/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 if (rli->workers.size() == i + 1) rli->workers.erase(i);
6544 }
6545 41276 return error;
6546 }
6547
6548 /**
6549 Initialization of the central rli members for Coordinator's role,
6550 communication channels such as Assigned Partition Hash (APH),
6551 and starting the Worker pool.
6552
6553 @param rli Pointer to Coordinator's Relay_log_info instance.
6554 @param n Number of configured Workers in the upcoming session.
6555 @param[out] mts_inited If the initialization processed was started.
6556
6557 @return 0 success
6558 non-zero as failure
6559 */
6560 10427 static int slave_start_workers(Relay_log_info *rli, ulong n, bool *mts_inited) {
6561 10427 int error = 0;
6562 /**
6563 gtid_monitoring_info must be cleared when MTS is enabled or
6564 workers_copy_pfs has elements
6565 */
6566 10427 bool clear_gtid_monitoring_info = false;
6567
6568 10427 mysql_mutex_assert_owner(&rli->run_lock);
6569
6570
3/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 10382 times.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
10427 if (n == 0 && rli->mts_recovery_group_cnt == 0) {
6571 45 rli->workers.clear();
6572 45 rli->clear_processing_trx();
6573 45 goto end;
6574 }
6575
6576 10382 *mts_inited = true;
6577
6578 /*
6579 The requested through argument number of Workers can be different
6580 from the previous time which ended with an error. Thereby
6581 the effective number of configured Workers is max of the two.
6582 */
6583 10382 rli->init_workers(max(n, rli->recovery_parallel_workers));
6584
6585 10382 rli->last_assigned_worker = nullptr; // associated with curr_group_assigned
6586
6587 /*
6588 GAQ queue holds seqno:s of scheduled groups. C polls workers in
6589 @c opt_mta_checkpoint_period to update GAQ (see @c next_event())
6590 The length of GAQ is set to be equal to checkpoint_group.
6591 Notice, the size matters for mta_checkpoint_routine's progress loop.
6592 */
6593
6594
1/2
✓ Branch 0 taken 10382 times.
✗ Branch 1 not taken.
10382 rli->gaq = new Slave_committed_queue(rli->checkpoint_group, n);
6595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10382 times.
10382 if (!rli->gaq->inited) return 1;
6596
6597 // length of WQ is actually constant though can be made configurable
6598 10382 rli->mts_slave_worker_queue_len_max = mts_slave_worker_queue_len_max;
6599 10382 rli->mts_pending_jobs_size = 0;
6600 10382 rli->mts_pending_jobs_size_max = ::opt_mts_pending_jobs_size_max;
6601 10382 rli->mts_wq_underrun_w_id = MTS_WORKER_UNDEF;
6602 10382 rli->mts_wq_excess_cnt = 0;
6603 10382 rli->mts_wq_overrun_cnt = 0;
6604 10382 rli->mts_wq_oversize = false;
6605 10382 rli->mts_coordinator_basic_nap = mts_coordinator_basic_nap;
6606 10382 rli->mts_worker_underrun_level = mts_worker_underrun_level;
6607 10382 rli->curr_group_seen_begin = rli->curr_group_seen_gtid = false;
6608 10382 rli->curr_group_isolated = false;
6609 10382 rli->rli_checkpoint_seqno = 0;
6610 10382 rli->mts_last_online_stat = time(nullptr);
6611 10382 rli->mts_group_status = Relay_log_info::MTS_NOT_IN_GROUP;
6612 10382 clear_gtid_monitoring_info = true;
6613
6614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10382 times.
10382 if (init_hash_workers(rli)) // MTS: mapping_db_to_worker
6615 {
6616 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_FAILED_TO_INIT_PARTITIONS_HASH);
6617 error = 1;
6618 goto err;
6619 }
6620
6621
2/2
✓ Branch 0 taken 41276 times.
✓ Branch 1 taken 10380 times.
51656 for (uint i = 0; i < n; i++) {
6622
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 41274 times.
41276 if ((error = slave_start_single_worker(rli, i))) goto err;
6623 41274 rli->replica_parallel_workers++;
6624 }
6625
6626 10380 end:
6627 /*
6628 Free the buffer that was being used to report worker's status through
6629 the table performance_schema.table_replication_applier_status_by_worker
6630 between stop slave and next start slave.
6631 */
6632
2/2
✓ Branch 0 taken 17780 times.
✓ Branch 1 taken 10425 times.
28205 for (int i = static_cast<int>(rli->workers_copy_pfs.size()) - 1; i >= 0;
6633 i--) {
6634
1/2
✓ Branch 0 taken 17780 times.
✗ Branch 1 not taken.
17780 delete rli->workers_copy_pfs[i];
6635
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 17771 times.
17780 if (!clear_gtid_monitoring_info) clear_gtid_monitoring_info = true;
6636 }
6637 10425 rli->workers_copy_pfs.clear();
6638
6639 // Effective end of the recovery right now when there is no gaps
6640
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10425 times.
✓ Branch 2 taken 216 times.
✓ Branch 3 taken 10209 times.
10425 if (!error && rli->mts_recovery_group_cnt == 0) {
6641
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10208 times.
10209 if ((error = rli->mts_finalize_recovery()))
6642 1 (void)Rpl_info_factory::reset_workers(rli);
6643
2/2
✓ Branch 0 taken 10208 times.
✓ Branch 1 taken 1 times.
10209 if (!error)
6644 10208 error = rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT);
6645 }
6646
6647 216 err:
6648
2/2
✓ Branch 0 taken 10391 times.
✓ Branch 1 taken 36 times.
10427 if (clear_gtid_monitoring_info) rli->clear_gtid_monitoring_info();
6649 10427 return error;
6650 }
6651
6652 /*
6653 Ending Worker threads.
6654
6655 Not in case Coordinator is killed itself, it first waits for
6656 Workers have finished their assignments, and then updates checkpoint.
6657 Workers are notified with setting KILLED status
6658 and waited for their acknowledgment as specified by
6659 worker's running_status.
6660 Coordinator finalizes with its MTS running status to reset few objects.
6661 */
6662 10087 static void slave_stop_workers(Relay_log_info *rli, bool *mts_inited) {
6663 10087 THD *thd = rli->info_thd;
6664
6665
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 10025 times.
10087 if (!*mts_inited)
6666 62 return;
6667
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10024 times.
10025 else if (rli->replica_parallel_workers == 0)
6668 1 goto end;
6669
6670 /*
6671 If request for stop slave is received notify worker
6672 to stop.
6673 */
6674 // Initialize worker exit count and max_updated_index to 0 during each stop.
6675 10024 rli->exit_counter = 0;
6676 20048 rli->max_updated_index = (rli->until_condition != Relay_log_info::UNTIL_NONE)
6677
2/2
✓ Branch 0 taken 1492 times.
✓ Branch 1 taken 8532 times.
10024 ? rli->mts_groups_assigned
6678 : 0;
6679
2/4
✓ Branch 0 taken 10024 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10024 times.
✗ Branch 3 not taken.
10024 if (!rli->workers.empty()) {
6680
3/4
✓ Branch 0 taken 10024 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39846 times.
✓ Branch 3 taken 10024 times.
49870 for (int i = static_cast<int>(rli->workers.size()) - 1; i >= 0; i--) {
6681
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39846 Slave_worker *w = rli->workers[i];
6682 39846 struct slave_job_item item = {nullptr, 0, 0};
6683 39846 struct slave_job_item *job_item = &item;
6684
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39846 mysql_mutex_lock(&w->jobs_lock);
6685
6686
2/2
✓ Branch 0 taken 839 times.
✓ Branch 1 taken 39007 times.
39846 if (w->running_status != Slave_worker::RUNNING) {
6687
1/2
✓ Branch 0 taken 839 times.
✗ Branch 1 not taken.
839 mysql_mutex_unlock(&w->jobs_lock);
6688 839 continue;
6689 }
6690
6691 39007 w->running_status = Slave_worker::STOP;
6692
1/2
✓ Branch 0 taken 39007 times.
✗ Branch 1 not taken.
39007 (void)set_max_updated_index_on_stop(w, job_item);
6693
1/2
✓ Branch 0 taken 39007 times.
✗ Branch 1 not taken.
39007 mysql_cond_signal(&w->jobs_cond);
6694
6695
1/2
✓ Branch 0 taken 39007 times.
✗ Branch 1 not taken.
39007 mysql_mutex_unlock(&w->jobs_lock);
6696
6697
3/10
✓ Branch 0 taken 39007 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39007 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 39007 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
39007 DBUG_PRINT("info", ("Notifying worker %lu%s to exit, thd %p", w->id,
6698 w->get_for_channel_str(), w->info_thd));
6699 }
6700 }
6701
1/2
✓ Branch 0 taken 10024 times.
✗ Branch 1 not taken.
10024 thd_proc_info(thd, "Waiting for workers to exit");
6702
6703
4/6
✓ Branch 0 taken 10024 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49870 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39846 times.
✓ Branch 5 taken 10024 times.
49870 for (Slave_worker **it = rli->workers.begin(); it != rli->workers.end();
6704 ++it) {
6705 39846 Slave_worker *w = *it;
6706
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39846 mysql_mutex_lock(&w->jobs_lock);
6707
2/2
✓ Branch 0 taken 15556 times.
✓ Branch 1 taken 39846 times.
55402 while (w->running_status != Slave_worker::NOT_RUNNING) {
6708 15556 PSI_stage_info old_stage;
6709
5/6
✓ Branch 0 taken 15267 times.
✓ Branch 1 taken 289 times.
✓ Branch 2 taken 13052 times.
✓ Branch 3 taken 2215 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 13052 times.
15556 assert(w->running_status == Slave_worker::ERROR_LEAVING ||
6710 w->running_status == Slave_worker::STOP ||
6711 w->running_status == Slave_worker::STOP_ACCEPTED);
6712
6713
1/2
✓ Branch 0 taken 15556 times.
✗ Branch 1 not taken.
15556 thd->ENTER_COND(&w->jobs_cond, &w->jobs_lock,
6714 &stage_replica_waiting_workers_to_exit, &old_stage);
6715
1/2
✓ Branch 0 taken 15556 times.
✗ Branch 1 not taken.
15556 mysql_cond_wait(&w->jobs_cond, &w->jobs_lock);
6716
1/2
✓ Branch 0 taken 15556 times.
✗ Branch 1 not taken.
15556 mysql_mutex_unlock(&w->jobs_lock);
6717
1/2
✓ Branch 0 taken 15556 times.
✗ Branch 1 not taken.
15556 thd->EXIT_COND(&old_stage);
6718
1/2
✓ Branch 0 taken 15556 times.
✗ Branch 1 not taken.
15556 mysql_mutex_lock(&w->jobs_lock);
6719 }
6720
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39846 mysql_mutex_unlock(&w->jobs_lock);
6721 }
6722
6723
4/6
✓ Branch 0 taken 10024 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49870 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39846 times.
✓ Branch 5 taken 10024 times.
49870 for (Slave_worker **it = rli->workers.begin(); it != rli->workers.end();
6724 ++it) {
6725 39846 Slave_worker *w = *it;
6726
6727 /*
6728 Make copies for reporting through the performance schema tables.
6729 This is preserved until the next START SLAVE.
6730 */
6731 Slave_worker *worker_copy = new Slave_worker(
6732 nullptr,
6733 #ifdef HAVE_PSI_INTERFACE
6734 &key_relay_log_info_run_lock, &key_relay_log_info_data_lock,
6735 &key_relay_log_info_sleep_lock, &key_relay_log_info_thd_lock,
6736 &key_relay_log_info_data_cond, &key_relay_log_info_start_cond,
6737 &key_relay_log_info_stop_cond, &key_relay_log_info_sleep_cond,
6738 #endif
6739
2/4
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39846 times.
✗ Branch 3 not taken.
39846 w->id, rli->get_channel());
6740
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39846 worker_copy->copy_values_for_PFS(w->id, w->running_status, w->info_thd,
6741 w->last_error(),
6742 w->get_gtid_monitoring_info());
6743
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39846 rli->workers_copy_pfs.push_back(worker_copy);
6744 }
6745
6746 /// @todo: consider to propagate an error out of the function
6747
3/4
✓ Branch 0 taken 9195 times.
✓ Branch 1 taken 829 times.
✓ Branch 2 taken 9195 times.
✗ Branch 3 not taken.
10024 if (thd->killed == THD::NOT_KILLED) (void)mta_checkpoint_routine(rli, false);
6748
6749 {
6750 10024 MUTEX_LOCK(lock, &rli->data_lock);
6751
3/4
✓ Branch 0 taken 49870 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39846 times.
✓ Branch 3 taken 10024 times.
49870 while (!rli->workers.empty()) {
6752
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39846 Slave_worker *w = rli->workers.back();
6753 // Free the current submode object
6754
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39846 delete w->current_mts_submode;
6755 39846 w->current_mts_submode = nullptr;
6756
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39846 rli->workers.pop_back();
6757
1/2
✓ Branch 0 taken 39846 times.
✗ Branch 1 not taken.
39846 delete w;
6758 }
6759 10024 }
6760
6761 struct timespec stats_end;
6762
1/2
✓ Branch 0 taken 10024 times.
✗ Branch 1 not taken.
10024 set_timespec_nsec(&stats_end, 0);
6763
6764
3/8
✓ Branch 0 taken 10024 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10024 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10024 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10024 DBUG_PRINT(
6765 "info",
6766 ("Total MTS session statistics: "
6767 "events processed = %llu; "
6768 "online time = %llu "
6769 "worker queues filled over overrun level = %lu "
6770 "waited due a Worker queue full = %lu "
6771 "waited due the total size = %lu "
6772 "total wait at clock conflicts = %llu "
6773 "found (count) workers occupied = %lu "
6774 "waited when workers occupied = %llu",
6775 rli->mts_events_assigned, diff_timespec(&stats_end, &rli->stats_begin),
6776 rli->mts_wq_overrun_cnt, rli->mts_wq_overfill_cnt,
6777 rli->wq_size_waits_cnt, rli->mts_total_wait_overlap.load(),
6778 rli->mts_wq_no_underrun_cnt, rli->mts_total_wait_worker_avail));
6779
6780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10024 times.
10024 assert(rli->pending_jobs == 0);
6781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10024 times.
10024 assert(rli->mts_pending_jobs_size == 0);
6782
6783 10025 end:
6784 10025 rli->mts_group_status = Relay_log_info::MTS_NOT_IN_GROUP;
6785
1/2
✓ Branch 0 taken 10025 times.
✗ Branch 1 not taken.
10025 destroy_hash_workers(rli);
6786
1/2
✓ Branch 0 taken 10025 times.
✗ Branch 1 not taken.
10025 delete rli->gaq;
6787
6788 // Destroy buffered events of the current group prior to exit.
6789
3/4
✓ Branch 0 taken 10062 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 10025 times.
10062 for (uint i = 0; i < rli->curr_group_da.size(); i++)
6790
2/4
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
37 delete rli->curr_group_da[i].data;
6791
1/2
✓ Branch 0 taken 10025 times.
✗ Branch 1 not taken.
10025 rli->curr_group_da.clear(); // GCDA
6792
6793
1/2
✓ Branch 0 taken 10025 times.
✗ Branch 1 not taken.
10025 rli->curr_group_assigned_parts.clear(); // GCAP
6794
1/2
✓ Branch 0 taken 10025 times.
✗ Branch 1 not taken.
10025 rli->deinit_workers();
6795 10025 rli->workers_array_initialized = false;
6796 10025 rli->replica_parallel_workers = 0;
6797
6798 10025 *mts_inited = false;
6799 }
6800
6801 /**
6802 Processes the outcome of applying an event, logs it properly if it's an error
6803 and return the proper error code to trigger.
6804
6805 @return the error code to bubble up in the execution stack.
6806 */
6807 84 static int report_apply_event_error(THD *thd, Relay_log_info *rli) {
6808
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 DBUG_TRACE;
6809 84 longlong slave_errno = 0;
6810
6811 /*
6812 retrieve as much info as possible from the thd and, error
6813 codes and warnings and print this to the error log as to
6814 allow the user to locate the error
6815 */
6816 84 uint32 const last_errno = rli->last_error().number;
6817
6818
3/4
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 80 times.
84 if (thd->is_error()) {
6819 4 char const *const errmsg = thd->get_stmt_da()->message_text();
6820
6821
3/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4 DBUG_PRINT("info", ("thd->get_stmt_da()->get_mysql_errno()=%d; "
6822 "rli->last_error.number=%d",
6823 thd->get_stmt_da()->mysql_errno(), last_errno));
6824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (last_errno == 0) {
6825 /*
6826 This function is reporting an error which was not reported
6827 while executing exec_relay_log_event().
6828 */
6829 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(), "%s", errmsg);
6830
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 } else if (last_errno != thd->get_stmt_da()->mysql_errno()) {
6831 /*
6832 * An error was reported while executing exec_relay_log_event()
6833 * however the error code differs from what is in the thread.
6834 * This function prints out more information to help finding
6835 * what caused the problem.
6836 */
6837
8/16
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
2 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_ADDITIONAL_ERROR_INFO_FROM_DA, errmsg,
6838 thd->get_stmt_da()->mysql_errno());
6839 }
6840 }
6841
6842 /* Print any warnings issued */
6843 Diagnostics_area::Sql_condition_iterator it =
6844
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 thd->get_stmt_da()->sql_conditions();
6845 const Sql_condition *err;
6846 /*
6847 Added controlled slave thread cancel for replication
6848 of user-defined variables.
6849 */
6850 84 bool udf_error = false;
6851
3/4
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 84 times.
88 while ((err = it++)) {
6852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (err->mysql_errno() == ER_CANT_OPEN_LIBRARY) udf_error = true;
6853
8/16
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4 times.
✗ Branch 15 not taken.
4 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_ERROR_INFO_FROM_DA, err->message_text(),
6854 err->mysql_errno());
6855 }
6856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (udf_error)
6857 slave_errno = ER_RPL_SLAVE_ERROR_LOADING_USER_DEFINED_LIBRARY;
6858 else
6859 84 slave_errno = ER_RPL_SLAVE_ERROR_RUNNING_QUERY;
6860
6861 84 return slave_errno;
6862 84 }
6863
6864 /**
6865 Slave SQL thread entry point.
6866
6867 @param arg Pointer to Relay_log_info object that holds information
6868 for the SQL thread.
6869
6870 @return Always 0.
6871 */
6872 10444 extern "C" void *handle_slave_sql(void *arg) {
6873 THD *thd; /* needs to be first for thread_stack */
6874 10444 bool thd_added = false;
6875 10444 bool main_loop_error = false;
6876 char llbuff[22], llbuff1[22];
6877 char saved_log_name[FN_REFLEN];
6878 char saved_master_log_name[FN_REFLEN];
6879 10444 my_off_t saved_log_pos = 0;
6880 10444 my_off_t saved_master_log_pos = 0;
6881 10444 my_off_t saved_skip = 0;
6882
6883 10444 Relay_log_info *rli = ((Master_info *)arg)->rli;
6884 const char *errmsg;
6885 10444 longlong slave_errno = 0;
6886 10444 bool mts_inited = false;
6887 10444 Global_THD_manager *thd_manager = Global_THD_manager::get_instance();
6888 10444 Commit_order_manager *commit_order_mngr = nullptr;
6889
1/2
✓ Branch 0 taken 10444 times.
✗ Branch 1 not taken.
10444 Rpl_applier_reader applier_reader(rli);
6890 10444 Relay_log_info::enum_priv_checks_status priv_check_status =
6891 Relay_log_info::enum_priv_checks_status::SUCCESS;
6892
6893 // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
6894
1/2
✓ Branch 0 taken 10444 times.
✗ Branch 1 not taken.
10444 my_thread_init();
6895 {
6896
1/2
✓ Branch 0 taken 10444 times.
✗ Branch 1 not taken.
10444 DBUG_TRACE;
6897
6898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10444 times.
10444 assert(rli->inited);
6899
1/2
✓ Branch 0 taken 10444 times.
✗ Branch 1 not taken.
10444 mysql_mutex_lock(&rli->run_lock);
6900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10444 times.
10444 assert(!rli->slave_running);
6901 10444 errmsg = nullptr;
6902 #ifndef NDEBUG
6903 10444 rli->events_until_exit = abort_slave_event_count;
6904 #endif
6905
6906
2/4
✓ Branch 0 taken 10444 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10444 times.
✗ Branch 3 not taken.
10444 thd = new THD; // note that constructor of THD uses DBUG_ !
6907 10444 thd->thread_stack = (char *)&thd; // remember where our stack is
6908
1/2
✓ Branch 0 taken 10444 times.
✗ Branch 1 not taken.
10444 mysql_mutex_lock(&rli->info_thd_lock);
6909 10444 rli->info_thd = thd;
6910
6911 #ifdef HAVE_PSI_THREAD_INTERFACE
6912 // save the instrumentation for SQL thread in rli->info_thd
6913
1/2
✓ Branch 0 taken 10444 times.
✗ Branch 1 not taken.
10444 struct PSI_thread *psi = PSI_THREAD_CALL(get_thread)();
6914
1/2
✓ Branch 0 taken 10444 times.
✗ Branch 1 not taken.
10444 thd_set_psi(rli->info_thd, psi);
6915 #endif
6916
1/2
✓ Branch 0 taken 10444 times.
✗ Branch 1 not taken.
10444 mysql_thread_set_psi_THD(thd);
6917
6918
2/2
✓ Branch 0 taken 10399 times.
✓ Branch 1 taken 45 times.
10444 if (rli->channel_mts_submode != MTS_PARALLEL_TYPE_DB_NAME)
6919
2/4
✓ Branch 0 taken 10399 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10399 times.
✗ Branch 3 not taken.
10399 rli->current_mts_submode = new Mts_submode_logical_clock();
6920 else
6921
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 rli->current_mts_submode = new Mts_submode_database();
6922
6923 // Only use replica preserve commit order if more than 1 worker exists
6924
6/8
✓ Branch 0 taken 10299 times.
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 10299 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10299 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10205 times.
✓ Branch 7 taken 239 times.
20743 if (opt_replica_preserve_commit_order && !rli->is_parallel_exec() &&
6925
2/2
✓ Branch 0 taken 10205 times.
✓ Branch 1 taken 94 times.
10299 rli->opt_replica_parallel_workers > 1)
6926 10205 commit_order_mngr =
6927
2/4
✓ Branch 0 taken 10205 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10205 times.
✗ Branch 3 not taken.
10205 new Commit_order_manager(rli->opt_replica_parallel_workers);
6928
6929 10444 rli->set_commit_order_manager(commit_order_mngr);
6930
6931
3/4
✓ Branch 0 taken 10444 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3608 times.
✓ Branch 3 taken 6836 times.
10444 if (channel_map.is_group_replication_channel_name(rli->get_channel())) {
6932
3/4
✓ Branch 0 taken 3608 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2296 times.
✓ Branch 3 taken 1312 times.
3608 if (channel_map.is_group_replication_channel_name(rli->get_channel(),
6933 true)) {
6934 2296 thd->rpl_thd_ctx.set_rpl_channel_type(GR_APPLIER_CHANNEL);
6935 } else {
6936 1312 thd->rpl_thd_ctx.set_rpl_channel_type(GR_RECOVERY_CHANNEL);
6937 }
6938 } else {
6939 6836 thd->rpl_thd_ctx.set_rpl_channel_type(RPL_STANDARD_CHANNEL);
6940 }
6941
6942
1/2
✓ Branch 0 taken 10444 times.
✗ Branch 1 not taken.
10444 mysql_mutex_unlock(&rli->info_thd_lock);
6943
6944 /* Inform waiting threads that slave has started */
6945 10444 rli->slave_run_id++;
6946 10444 rli->slave_running = 1;
6947 10444 rli->reported_unsafe_warning = false;
6948 10444 rli->sql_thread_kill_accepted = false;
6949
6950
3/4
✓ Branch 0 taken 10444 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 10438 times.
10444 if (init_replica_thread(thd, SLAVE_THD_SQL)) {
6951 /*
6952 TODO: this is currently broken - slave start and change master
6953 will be stuck if we fail here
6954 */
6955
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 mysql_cond_broadcast(&rli->start_cond);
6956
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 mysql_mutex_unlock(&rli->run_lock);
6957
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6958 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
6959 "Failed during slave thread initialization");
6960 6 goto err;
6961 }
6962
1/2
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
10438 thd->init_query_mem_roots();
6963
6964
3/4
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 194 times.
✓ Branch 3 taken 10244 times.
10438 if ((rli->deferred_events_collecting = rli->rpl_filter->is_on()))
6965
2/4
✓ Branch 0 taken 194 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 194 times.
✗ Branch 3 not taken.
194 rli->deferred_events = new Deferred_log_events();
6966 10438 thd->rli_slave = rli;
6967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10438 times.
10438 assert(thd->rli_slave->info_thd == thd);
6968
6969 10438 thd->temporary_tables = rli->save_temporary_tables; // restore temp tables
6970
1/2
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
10438 set_thd_in_use_temporary_tables(
6971 rli); // (re)set sql_thd in use for saved temp tables
6972 /* Set applier thread InnoDB priority */
6973
1/2
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
10438 set_thd_tx_priority(thd, rli->get_thd_tx_priority());
6974
6975 /* Set write set related options */
6976
1/2
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
10438 set_thd_write_set_options(thd, rli->get_ignore_write_set_memory_limit(),
6977 10438 rli->get_allow_drop_write_set());
6978
6979
1/2
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
10438 thd->variables.require_row_format = rli->is_row_format_required();
6980
6981 10438 if (Relay_log_info::PK_CHECK_STREAM !=
6982
3/4
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 10421 times.
10438 rli->get_require_table_primary_key_check())
6983 17 thd->variables.sql_require_primary_key =
6984
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 (rli->get_require_table_primary_key_check() ==
6985 Relay_log_info::PK_CHECK_ON);
6986
6987 // Replicas shall not create GIPKs if source tables have no PKs
6988 10438 thd->variables.sql_generate_invisible_primary_key = false;
6989
6990
1/2
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
10438 rli->transaction_parser.reset();
6991
6992
1/2
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
10438 thd_manager->add_thd(thd);
6993 10438 thd_added = true;
6994
6995 10438 rli->stats_exec_time = rli->stats_read_time = 0;
6996
1/2
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
10438 set_timespec_nsec(&rli->ts_exec[0], 0);
6997
1/2
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
10438 set_timespec_nsec(&rli->ts_exec[1], 0);
6998
1/2
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
10438 set_timespec_nsec(&rli->stats_begin, 0);
6999
7000
6/8
✓ Branch 0 taken 10438 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6574 times.
✓ Branch 3 taken 3864 times.
✓ Branch 4 taken 3864 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 10427 times.
10438 if (RUN_HOOK(binlog_relay_io, applier_start, (thd, rli->mi))) {
7001
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 mysql_cond_broadcast(&rli->start_cond);
7002
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 mysql_mutex_unlock(&rli->run_lock);
7003
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
7004 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
7005 "Failed to run 'applier_start' hook");
7006 11 goto err;
7007 }
7008
7009 /* MTS: starting the worker pool */
7010
1/2
✓ Branch 0 taken 10427 times.
✗ Branch 1 not taken.
10427 if (slave_start_workers(rli, rli->opt_replica_parallel_workers,
7011
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10424 times.
10427 &mts_inited) != 0) {
7012
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mysql_cond_broadcast(&rli->start_cond);
7013
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mysql_mutex_unlock(&rli->run_lock);
7014
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
7015 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
7016 "Failed during slave workers initialization");
7017 3 goto err;
7018 }
7019 /*
7020 We are going to set slave_running to 1. Assuming slave I/O thread is
7021 alive and connected, this is going to make Seconds_Behind_Master be 0
7022 i.e. "caught up". Even if we're just at start of thread. Well it's ok, at
7023 the moment we start we can think we are caught up, and the next second we
7024 start receiving data so we realize we are not caught up and
7025 Seconds_Behind_Master grows. No big deal.
7026 */
7027 10424 rli->abort_slave = false;
7028
7029 /*
7030 Reset errors for a clean start (otherwise, if the master is idle, the SQL
7031 thread may execute no Query_log_event, so the error will remain even
7032 though there's no problem anymore). Do not reset the master timestamp
7033 (imagine the slave has caught everything, the STOP SLAVE and START SLAVE:
7034 as we are not sure that we are going to receive a query, we want to
7035 remember the last master timestamp (to say how many seconds behind we are
7036 now.
7037 But the master timestamp is reset by RESET SLAVE & CHANGE MASTER.
7038 */
7039
1/2
✓ Branch 0 taken 10424 times.
✗ Branch 1 not taken.
10424 rli->clear_error();
7040
2/2
✓ Branch 0 taken 10379 times.
✓ Branch 1 taken 45 times.
10424 if (rli->workers_array_initialized) {
7041
3/4
✓ Branch 0 taken 51650 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41271 times.
✓ Branch 3 taken 10379 times.
51650 for (size_t i = 0; i < rli->get_worker_count(); i++) {
7042
2/4
✓ Branch 0 taken 41271 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41271 times.
✗ Branch 3 not taken.
41271 rli->get_worker(i)->clear_error();
7043 }
7044 }
7045
7046
3/6
✓ Branch 0 taken 10424 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10424 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10424 times.
20848 if (rli->update_is_transactional() ||
7047
2/4
✓ Branch 0 taken 10424 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10424 times.
10424 DBUG_EVALUATE_IF("simulate_update_is_transactional_error", true,
7048 false)) {
7049 mysql_cond_broadcast(&rli->start_cond);
7050 mysql_mutex_unlock(&rli->run_lock);
7051 rli->report(
7052 ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, ER_THD(thd, ER_SLAVE_FATAL_ERROR),
7053 "Error checking if the relay log repository is transactional.");
7054 goto err;
7055 }
7056
7057
3/4
✓ Branch 0 taken 10424 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 10360 times.
10424 if (!rli->is_transactional())
7058
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 rli->report(
7059 WARNING_LEVEL, 0,
7060 "If a crash happens this configuration does not guarantee that "
7061 "the relay "
7062 "log info will be consistent");
7063
7064
1/2
✓ Branch 0 taken 10424 times.
✗ Branch 1 not taken.
10424 mysql_cond_broadcast(&rli->start_cond);
7065
1/2
✓ Branch 0 taken 10424 times.
✗ Branch 1 not taken.
10424 mysql_mutex_unlock(&rli->run_lock);
7066
7067
2/4
✓ Branch 0 taken 10424 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10424 times.
✗ Branch 3 not taken.
10424 DEBUG_SYNC(thd, "after_start_replica");
7068
7069 // tell the I/O thread to take relay_log_space_limit into account from now
7070 // on
7071
1/2
✓ Branch 0 taken 10424 times.
✗ Branch 1 not taken.
10424 mysql_mutex_lock(&rli->log_space_lock);
7072 10424 rli->ignore_log_space_limit = false;
7073
1/2
✓ Branch 0 taken 10424 times.
✗ Branch 1 not taken.
10424 mysql_mutex_unlock(&rli->log_space_lock);
7074 10424 rli->trans_retries = 0; // start from "no error"
7075
3/8
✓ Branch 0 taken 10424 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10424 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10424 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10424 DBUG_PRINT("info", ("rli->trans_retries: %lu", rli->trans_retries));
7076
7077
3/4
✓ Branch 0 taken 10424 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 10418 times.
10424 if (applier_reader.open(&errmsg)) {
7078
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, "%s", errmsg);
7079 6 goto err;
7080 }
7081
7082
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10418 times.
10418 THD_CHECK_SENTRY(thd);
7083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10418 times.
10418 assert(rli->info_thd == thd);
7084
7085
3/10
✓ Branch 0 taken 10418 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10418 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10418 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
10418 DBUG_PRINT("master_info", ("log_file_name: %s position: %s",
7086 rli->get_group_master_log_name(),
7087 llstr(rli->get_group_master_log_pos(), llbuff)));
7088
7089
3/4
✓ Branch 0 taken 10418 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 10415 times.
10418 if (check_temp_dir(rli->slave_patternload_file, rli->get_channel())) {
7090
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
7091 "Unable to use slave's temporary directory %s - %s",
7092 replica_load_tmpdir, thd->get_stmt_da()->message_text());
7093 3 goto err;
7094 }
7095
7096
1/2
✓ Branch 0 taken 10415 times.
✗ Branch 1 not taken.
10415 priv_check_status = rli->check_privilege_checks_user();
7097
3/4
✓ Branch 0 taken 10415 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 10414 times.
10415 if (!!priv_check_status) {
7098
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report_privilege_check_error(ERROR_LEVEL, priv_check_status,
7099 false /* to client*/);
7100
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->set_privilege_checks_user_corrupted(true);
7101 1 goto err;
7102 }
7103 priv_check_status =
7104
1/2
✓ Branch 0 taken 10414 times.
✗ Branch 1 not taken.
10414 rli->initialize_applier_security_context(); // Applier security context
7105 // initialization with
7106 // `PRIVILEGE_CHECKS_USER`
7107
3/4
✓ Branch 0 taken 10414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 10412 times.
10414 if (!!priv_check_status) {
7108
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 rli->report_privilege_check_error(ERROR_LEVEL, priv_check_status,
7109 false /* to client*/);
7110 2 goto err;
7111 }
7112
7113
3/4
✓ Branch 0 taken 10412 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10233 times.
✓ Branch 3 taken 179 times.
10412 if (rli->is_privilege_checks_user_null())
7114
11/22
✓ Branch 0 taken 10233 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10233 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10233 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10233 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10233 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 10233 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 10233 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 10233 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 10233 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 10233 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 10233 times.
✗ Branch 21 not taken.
10233 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_SQL_THREAD_STARTING,
7115 rli->get_for_channel_str(), rli->get_rpl_log_name(),
7116 llstr(rli->get_group_master_log_pos_info(), llbuff),
7117 rli->get_group_relay_log_name(),
7118 llstr(rli->get_group_relay_log_pos(), llbuff1));
7119 else
7120
14/28
✓ Branch 0 taken 179 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 179 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 179 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 179 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 179 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 179 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 179 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 179 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 179 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 179 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 179 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 179 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 179 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 179 times.
✗ Branch 27 not taken.
179 LogErr(INFORMATION_LEVEL,
7121 ER_RPL_SLAVE_SQL_THREAD_STARTING_WITH_PRIVILEGE_CHECKS,
7122 rli->get_for_channel_str(), rli->get_rpl_log_name(),
7123 llstr(rli->get_group_master_log_pos_info(), llbuff),
7124 rli->get_group_relay_log_name(),
7125 llstr(rli->get_group_relay_log_pos(), llbuff1),
7126 rli->get_privilege_checks_username().c_str(),
7127 rli->get_privilege_checks_hostname().c_str(),
7128 opt_always_activate_granted_roles == 0 ? "DEFAULT" : "ALL");
7129
7130 /* execute init_replica variable */
7131
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 10398 times.
10412 if (opt_init_replica.length) {
7132
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 execute_init_command(thd, &opt_init_replica, &LOCK_sys_init_replica);
7133
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11 times.
14 if (thd->is_slave_error) {
7134
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 rli->report(ERROR_LEVEL, ER_SERVER_SLAVE_INIT_QUERY_FAILED,
7135
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 ER_THD(current_thd, ER_SERVER_SLAVE_INIT_QUERY_FAILED),
7136 thd->get_stmt_da()->mysql_errno(),
7137 thd->get_stmt_da()->message_text());
7138 3 goto err;
7139 }
7140 }
7141
7142 /*
7143 First check until condition - probably there is nothing to execute. We
7144 do not want to wait for next event in this case.
7145 */
7146
1/2
✓ Branch 0 taken 10409 times.
✗ Branch 1 not taken.
10409 mysql_mutex_lock(&rli->data_lock);
7147
2/2
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 10067 times.
10409 if (rli->slave_skip_counter) {
7148
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 strmake(saved_log_name, rli->get_group_relay_log_name(), FN_REFLEN - 1);
7149
1/2
✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
342 strmake(saved_master_log_name, rli->get_group_master_log_name(),
7150 FN_REFLEN - 1);
7151 342 saved_log_pos = rli->get_group_relay_log_pos();
7152 342 saved_master_log_pos = rli->get_group_master_log_pos();
7153 342 saved_skip = rli->slave_skip_counter;
7154 }
7155
3/4
✓ Branch 0 taken 10409 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 10378 times.
10409 if (rli->is_until_satisfied_at_start_slave()) {
7156
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 mysql_mutex_unlock(&rli->data_lock);
7157 31 goto err;
7158 }
7159
1/2
✓ Branch 0 taken 10378 times.
✗ Branch 1 not taken.
10378 mysql_mutex_unlock(&rli->data_lock);
7160
7161 /* Read queries from the IO/THREAD until this thread is killed */
7162
7163
7/8
✓ Branch 0 taken 1873725 times.
✓ Branch 1 taken 8594 times.
✓ Branch 2 taken 1873725 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1872298 times.
✓ Branch 5 taken 1427 times.
✓ Branch 6 taken 1872298 times.
✓ Branch 7 taken 10021 times.
1882319 while (!main_loop_error && !sql_slave_killed(thd, rli)) {
7164 1872298 Log_event *ev = nullptr;
7165
1/2
✓ Branch 0 taken 1872298 times.
✗ Branch 1 not taken.
1872298 THD_STAGE_INFO(thd, stage_reading_event_from_the_relay_log);
7166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1872298 times.
1872298 assert(rli->info_thd == thd);
7167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1872298 times.
1872298 THD_CHECK_SENTRY(thd);
7168
6/6
✓ Branch 0 taken 2151 times.
✓ Branch 1 taken 1870147 times.
✓ Branch 2 taken 341 times.
✓ Branch 3 taken 1810 times.
✓ Branch 4 taken 341 times.
✓ Branch 5 taken 1871957 times.
1872298 if (saved_skip && rli->slave_skip_counter == 0) {
7169
8/16
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 341 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 341 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 341 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 341 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 341 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 341 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 341 times.
✗ Branch 15 not taken.
341 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_SKIP_COUNTER_EXECUTED,
7170 (ulong)saved_skip, saved_log_name, (ulong)saved_log_pos,
7171 saved_master_log_name, (ulong)saved_master_log_pos,
7172 rli->get_group_relay_log_name(),
7173 (ulong)rli->get_group_relay_log_pos(),
7174 rli->get_group_master_log_name_info(),
7175 (ulong)rli->get_group_master_log_pos_info());
7176 341 saved_skip = 0;
7177 }
7178
7179 // read next event
7180
1/2
✓ Branch 0 taken 1872298 times.
✗ Branch 1 not taken.
1872298 mysql_mutex_lock(&rli->data_lock);
7181
1/2
✓ Branch 0 taken 1872151 times.
✗ Branch 1 not taken.
1872298 ev = applier_reader.read_next_event();
7182
1/2
✓ Branch 0 taken 1872151 times.
✗ Branch 1 not taken.
1872151 mysql_mutex_unlock(&rli->data_lock);
7183
7184 // set additional context as needed by the scheduler before execution
7185 // takes place
7186
7/8
✓ Branch 0 taken 1863734 times.
✓ Branch 1 taken 8417 times.
✓ Branch 2 taken 1863734 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1861956 times.
✓ Branch 5 taken 1778 times.
✓ Branch 6 taken 1861956 times.
✓ Branch 7 taken 10195 times.
3734107 if (ev != nullptr && rli->is_parallel_exec() &&
7187
1/2
✓ Branch 0 taken 1861956 times.
✗ Branch 1 not taken.
1861956 rli->current_mts_submode != nullptr)
7188
1/2
✓ Branch 0 taken 1861956 times.
✗ Branch 1 not taken.
1861956 rli->current_mts_submode->set_multi_threaded_applier_context(*rli, *ev);
7189
7190 // try to execute the event
7191
3/5
✓ Branch 0 taken 1871941 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1863347 times.
✓ Branch 3 taken 8594 times.
✗ Branch 4 not taken.
1872151 switch (exec_relay_log_event(thd, rli, &applier_reader, ev)) {
7192 1863347 case SLAVE_APPLY_EVENT_AND_UPDATE_POS_OK:
7193 /** success, we read the next event. */
7194 /** fall through */
7195 case SLAVE_APPLY_EVENT_UNTIL_REACHED:
7196 /** this will make the main loop abort in the next iteration */
7197 /** fall through */
7198 case SLAVE_APPLY_EVENT_RETRY:
7199 /** single threaded applier has to retry.
7200 Next iteration reads the same event. */
7201 1863347 break;
7202
7203 8594 case SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPLY_ERROR:
7204 /** fall through */
7205 case SLAVE_APPLY_EVENT_AND_UPDATE_POS_UPDATE_POS_ERROR:
7206 /** fall through */
7207 case SLAVE_APPLY_EVENT_AND_UPDATE_POS_APPEND_JOB_ERROR:
7208 8594 main_loop_error = true;
7209 8594 break;
7210
7211 default:
7212 /* This shall never happen. */
7213 assert(0); /* purecov: inspected */
7214 break;
7215 }
7216 }
7217 10021 err:
7218
7219 // report error
7220
7/8
✓ Branch 0 taken 8594 times.
✓ Branch 1 taken 1493 times.
✓ Branch 2 taken 8594 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 84 times.
✓ Branch 5 taken 8510 times.
✓ Branch 6 taken 84 times.
✓ Branch 7 taken 10003 times.
10087 if (main_loop_error == true && !sql_slave_killed(thd, rli))
7221
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 slave_errno = report_apply_event_error(thd, rli);
7222
7223 /* At this point the SQL thread will not try to work anymore. */
7224 10087 rli->atomic_is_stopping = true;
7225
7/10
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3849 times.
✓ Branch 3 taken 6238 times.
✓ Branch 4 taken 3788 times.
✓ Branch 5 taken 61 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3788 times.
✓ Branch 8 taken 3849 times.
✗ Branch 9 not taken.
10087 (void)RUN_HOOK(
7226 binlog_relay_io, applier_stop,
7227 (thd, rli->mi, rli->is_error() || !rli->sql_thread_kill_accepted));
7228
7229
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 slave_stop_workers(rli, &mts_inited); // stopping worker pool
7230 /* Thread stopped. Print the current replication position to the log */
7231
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 10003 times.
10087 if (slave_errno)
7232
9/18
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 84 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 84 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 84 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 84 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 84 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 84 times.
✗ Branch 17 not taken.
84 LogErr(ERROR_LEVEL, slave_errno, rli->get_rpl_log_name(),
7233 llstr(rli->get_group_master_log_pos_info(), llbuff));
7234 else
7235
10/20
✓ Branch 0 taken 10003 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10003 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10003 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10003 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10003 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 10003 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 10003 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 10003 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 10003 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 10003 times.
✗ Branch 19 not taken.
10003 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_SQL_THREAD_EXITING,
7236 rli->get_for_channel_str(), rli->get_rpl_log_name(),
7237 llstr(rli->get_group_master_log_pos_info(), llbuff));
7238
7239
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 delete rli->current_mts_submode;
7240 10087 rli->current_mts_submode = nullptr;
7241
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 rli->clear_mts_recovery_groups();
7242
7243 /*
7244 Some events set some playgrounds, which won't be cleared because thread
7245 stops. Stopping of this thread may not be known to these events ("stop"
7246 request is detected only by the present function, not by events), so we
7247 must "proactively" clear playgrounds:
7248 */
7249
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 thd->clear_error();
7250
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 rli->cleanup_context(thd, true);
7251 /*
7252 Some extra safety, which should not been needed (normally, event deletion
7253 should already have done these assignments (each event which sets these
7254 variables is supposed to set them to 0 before terminating)).
7255 */
7256 10087 thd->set_catalog(NULL_CSTR);
7257
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 thd->reset_query();
7258
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 thd->reset_db(NULL_CSTR);
7259
7260 /*
7261 Pause the SQL thread and wait for 'continue_to_stop_sql_thread'
7262 signal to continue to shutdown the SQL thread.
7263 */
7264
4/6
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 10084 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
10087 DBUG_EXECUTE_IF("pause_after_sql_thread_stop_hook", {
7265 rpl_replica_debug_point(DBUG_RPL_S_AFTER_SQL_STOP, thd);
7266 };);
7267
7268
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 THD_STAGE_INFO(thd, stage_waiting_for_replica_mutex_on_exit);
7269
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 mysql_mutex_lock(&rli->run_lock);
7270 /* We need data_lock, at least to wake up any waiting source_pos_wait() */
7271
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 mysql_mutex_lock(&rli->data_lock);
7272
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 applier_reader.close();
7273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10087 times.
10087 assert(rli->slave_running == 1); // tracking buffer overrun
7274 /* When source_pos_wait() wakes up it will check this and terminate */
7275 10087 rli->slave_running = 0;
7276 10087 rli->atomic_is_stopping = false;
7277 /* Forget the relay log's format */
7278
2/4
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10087 times.
10087 if (rli->set_rli_description_event(nullptr)) {
7279 #ifndef NDEBUG
7280 bool set_rli_description_event_failed = false;
7281 #endif
7282 assert(set_rli_description_event_failed);
7283 }
7284 /* Wake up source_pos_wait() */
7285
3/8
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10087 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10087 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10087 DBUG_PRINT("info",
7286 ("Signaling possibly waiting source_pos_wait() functions"));
7287
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 mysql_cond_broadcast(&rli->data_cond);
7288
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 mysql_mutex_unlock(&rli->data_lock);
7289 10087 rli->ignore_log_space_limit = false; /* don't need any lock */
7290 10087 rli->sql_force_rotate_relay = false;
7291 /* we die so won't remember charset - re-update them on next thread start */
7292
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 rli->cached_charset_invalidate();
7293 10087 rli->save_temporary_tables = thd->temporary_tables;
7294
7295 /*
7296 TODO: see if we can do this conditionally in next_event() instead
7297 to avoid unneeded position re-init
7298 */
7299 10087 thd->temporary_tables =
7300 nullptr; // remove temptation from destructor to close them
7301 // destructor will not free it, because we are weird
7302
2/4
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10087 times.
✗ Branch 3 not taken.
10087 thd->get_protocol_classic()->end_net();
7303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10087 times.
10087 assert(rli->info_thd == thd);
7304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10087 times.
10087 THD_CHECK_SENTRY(thd);
7305
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 mysql_mutex_lock(&rli->info_thd_lock);
7306 10087 rli->info_thd = nullptr;
7307
2/2
✓ Branch 0 taken 9848 times.
✓ Branch 1 taken 239 times.
10087 if (commit_order_mngr) {
7308 9848 rli->set_commit_order_manager(nullptr);
7309
1/2
✓ Branch 0 taken 9848 times.
✗ Branch 1 not taken.
9848 delete commit_order_mngr;
7310 }
7311
7312
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 mysql_mutex_unlock(&rli->info_thd_lock);
7313
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 set_thd_in_use_temporary_tables(
7314 rli); // (re)set info_thd in use for saved temp tables
7315
7316
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 thd->release_resources();
7317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10087 times.
10087 THD_CHECK_SENTRY(thd);
7318
3/4
✓ Branch 0 taken 10081 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 10081 times.
✗ Branch 3 not taken.
10087 if (thd_added) thd_manager->remove_thd(thd);
7319
7320 /*
7321 The thd can only be destructed after indirect references
7322 through mi->rli->info_thd are cleared: mi->rli->info_thd= NULL.
7323
7324 For instance, user thread might be issuing show_slave_status
7325 and attempting to read mi->rli->info_thd->proc_info().
7326 Therefore thd must only be deleted after info_thd is set
7327 to NULL.
7328 */
7329
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 mysql_thread_set_psi_THD(nullptr);
7330
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 delete thd;
7331
7332 /*
7333 Note: the order of the broadcast and unlock calls below (first broadcast,
7334 then unlock) is important. Otherwise a killer_thread can execute between
7335 the calls and delete the mi structure leading to a crash! (see BUG#25306
7336 for details)
7337 */
7338
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 mysql_cond_broadcast(&rli->stop_cond);
7339
4/6
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 10084 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
10087 DBUG_EXECUTE_IF("simulate_replica_delay_at_terminate_bug38694", sleep(5););
7340
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 mysql_mutex_unlock(&rli->run_lock); // tell the world we are done
7341 10087 }
7342
1/2
✓ Branch 0 taken 10087 times.
✗ Branch 1 not taken.
10087 my_thread_end();
7343 #if OPENSSL_VERSION_NUMBER < 0x10100000L
7344 ERR_remove_thread_state(0);
7345 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
7346 10087 my_thread_exit(nullptr);
7347 return nullptr; // Avoid compiler warnings
7348 10087 }
7349
7350 /**
7351 Used by the slave IO thread when it receives a rotate event from the
7352 master.
7353
7354 Updates the master info with the place in the next binary log where
7355 we should start reading. Rotate the relay log to avoid mixed-format
7356 relay logs.
7357
7358 @param mi master_info for the slave
7359 @param rev The rotate log event read from the master
7360
7361 @note The caller must hold mi->data_lock before invoking this function.
7362
7363 @retval 0 ok
7364 @retval 1 error
7365 */
7366 18914 static int process_io_rotate(Master_info *mi, Rotate_log_event *rev) {
7367
1/2
✓ Branch 0 taken 18914 times.
✗ Branch 1 not taken.
18914 DBUG_TRACE;
7368 18914 mysql_mutex_assert_owner(mi->rli->relay_log.get_log_lock());
7369
7370
2/4
✓ Branch 0 taken 18914 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18914 times.
18914 if (unlikely(!rev->is_valid())) return 1;
7371
7372 #ifndef NDEBUG
7373 /*
7374 If we do not do this, we will be getting the first
7375 rotate event forever, so we need to not disconnect after one.
7376 */
7377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18914 times.
18914 if (disconnect_slave_event_count) mi->events_until_exit++;
7378 #endif
7379
7380 /*
7381 Master will send a FD event immediately after the Roate event, so don't log
7382 the current FD event.
7383 */
7384
1/2
✓ Branch 0 taken 18914 times.
✗ Branch 1 not taken.
18914 int ret = rotate_relay_log(mi, false, false, true);
7385
7386
1/2
✓ Branch 0 taken 18914 times.
✗ Branch 1 not taken.
18914 mysql_mutex_lock(&mi->data_lock);
7387 /* Safe copy as 'rev' has been "sanitized" in Rotate_log_event's ctor */
7388 37828 memcpy(const_cast<char *>(mi->get_master_log_name()), rev->new_log_ident,
7389 18914 rev->ident_len + 1);
7390 18914 mi->set_master_log_pos(rev->pos);
7391
3/8
✓ Branch 0 taken 18914 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18914 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 18914 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
18914 DBUG_PRINT("info",
7392 ("new (master_log_name, master_log_pos): ('%s', %lu)",
7393 mi->get_master_log_name(), (ulong)mi->get_master_log_pos()));
7394
1/2
✓ Branch 0 taken 18914 times.
✗ Branch 1 not taken.
18914 mysql_mutex_unlock(&mi->data_lock);
7395
7396 18914 return ret;
7397 18914 }
7398
7399 3415 int heartbeat_queue_event(bool is_valid, Master_info *&mi,
7400 std::string binlog_name, uint64_t position,
7401 unsigned long &inc_pos, bool &do_flush_mi) {
7402
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3415 times.
3415 if (!is_valid) {
7403 char errbuf[1024];
7404 char llbuf[22];
7405 sprintf(errbuf,
7406 "inconsistent heartbeat event content; the event's data: "
7407 "log_file_name %-.512s log_pos %s",
7408 binlog_name.c_str(), llstr(position, llbuf));
7409 mi->report(ERROR_LEVEL, ER_SLAVE_HEARTBEAT_FAILURE,
7410 ER_THD(current_thd, ER_SLAVE_HEARTBEAT_FAILURE), errbuf);
7411 return 1;
7412 }
7413
1/2
✓ Branch 0 taken 3415 times.
✗ Branch 1 not taken.
3415 mysql_mutex_lock(&mi->data_lock);
7414 3415 mi->received_heartbeats++;
7415 3415 mi->last_heartbeat = my_getsystime() / 10;
7416 std::string mi_log_filename{
7417
2/4
✓ Branch 0 taken 3415 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3415 times.
✗ Branch 3 not taken.
3415 mi->get_master_log_name() != nullptr ? mi->get_master_log_name() : ""};
7418
7419 /*
7420 compare local and event's versions of log_file, log_pos.
7421
7422 Heartbeat is sent only after an event corresponding to the coordinates
7423 the heartbeat carries.
7424 Slave can not have a difference in coordinates except in the
7425 special case when mi->get_master_log_name(), mi->get_master_log_pos()
7426 have never been updated by Rotate event i.e when slave does not have
7427 any history with the master (and thereafter mi->get_master_log_pos() is
7428 NULL).
7429
7430 TODO: handling `when' for SHOW REPLICA STATUS' snds behind
7431 */
7432
2/4
✓ Branch 0 taken 3415 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3415 times.
3415 if (mi_log_filename.compare(binlog_name) != 0) {
7433 std::ostringstream oss;
7434 oss << "Replication heartbeat event contained the filename '" << binlog_name
7435 << "' which is different from '" << mi_log_filename
7436 << "' that was specified in earlier Rotate events.";
7437 mi->report(ERROR_LEVEL, ER_SLAVE_HEARTBEAT_FAILURE,
7438 ER_THD(current_thd, ER_SLAVE_HEARTBEAT_FAILURE),
7439 oss.str().c_str());
7440 return 1;
7441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3415 times.
3415 } else if (mi->get_master_log_pos() > position) {
7442 std::ostringstream oss;
7443 oss << "Replication heartbeat event contained the position " << position
7444 << " which is smaller than the position " << mi->get_master_log_pos()
7445 << " that was computed from earlier events received in the stream. "
7446 << "The filename is '" << mi_log_filename << "'.";
7447 mi->report(ERROR_LEVEL, ER_SLAVE_HEARTBEAT_FAILURE,
7448 ER_THD(current_thd, ER_SLAVE_HEARTBEAT_FAILURE),
7449 oss.str().c_str());
7450 return 1;
7451 }
7452 /*
7453 During GTID protocol, if the master skips transactions,
7454 a heartbeat event is sent to the slave at the end of last
7455 skipped transaction to update coordinates.
7456
7457 I/O thread receives the heartbeat event and updates mi
7458 only if the received heartbeat position is greater than
7459 mi->get_master_log_pos(). This event is written to the
7460 relay log as an ignored Rotate event. SQL thread reads
7461 the rotate event only to update the coordinates corresponding
7462 to the last skipped transaction. Note that,
7463 we update only the positions and not the file names, as a ROTATE
7464 EVENT from the master prior to this will update the file name.
7465
7466 When master's binlog is PS 5_7 encrypted it will also sent heartbeat
7467 event after reading Start_encryption_event from the binlog.
7468 As Start_encryption_event is not sent to slave, the master
7469 informs the slave to update it's master_log_pos by sending
7470 heartbeat event.
7471 */
7472
5/6
✓ Branch 0 taken 901 times.
✓ Branch 1 taken 2514 times.
✓ Branch 2 taken 901 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 901 times.
✓ Branch 5 taken 2514 times.
3415 if (mi->get_master_log_pos() < position && !mi_log_filename.empty()) {
7473
4/6
✓ Branch 0 taken 901 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 899 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
901 DBUG_EXECUTE_IF("reached_heart_beat_queue_event",
7474 { rpl_replica_debug_point(DBUG_RPL_S_HEARTBEAT_EV); };);
7475 901 mi->set_master_log_pos(position);
7476
7477 /*
7478 Put this heartbeat event in the relay log as a Rotate Event.
7479 */
7480 901 inc_pos = 0;
7481
1/2
✓ Branch 0 taken 901 times.
✗ Branch 1 not taken.
901 mysql_mutex_unlock(&mi->data_lock);
7482
2/4
✓ Branch 0 taken 901 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 901 times.
901 if (write_rotate_to_master_pos_into_relay_log(mi->info_thd, mi, false
7483 /* force_flush_mi_info */))
7484 return 0;
7485 901 do_flush_mi = false; /* write_rotate_... above flushed master info */
7486 } else
7487
1/2
✓ Branch 0 taken 2514 times.
✗ Branch 1 not taken.
2514 mysql_mutex_unlock(&mi->data_lock);
7488
7489 3415 return 0;
7490 3415 }
7491
7492 /**
7493 Store an event received from the master connection into the relay
7494 log.
7495
7496 @param mi The Master_info object representing this connection.
7497 @param buf Pointer to the event data.
7498 @param event_len Length of event data.
7499 @param do_flush_mi True to flush master info after successfully queuing the
7500 event.
7501
7502 @retval QUEUE_EVENT_OK on success.
7503 @retval QUEUE_EVENT_ERROR_QUEUING if there was an error while queuing.
7504 @retval QUEUE_EVENT_ERROR_FLUSHING_INFO if there was an error while
7505 flushing master info.
7506
7507 @todo Make this a member of Master_info.
7508 */
7509 1778311 QUEUE_EVENT_RESULT queue_event(Master_info *mi, const char *buf,
7510 ulong event_len, bool do_flush_mi) {
7511 1778311 QUEUE_EVENT_RESULT res = QUEUE_EVENT_OK;
7512 1778311 ulong inc_pos = 0;
7513 1778311 Relay_log_info *rli = mi->rli;
7514 1778311 mysql_mutex_t *log_lock = rli->relay_log.get_log_lock();
7515 ulong s_id;
7516 1778311 int lock_count = 0;
7517
7518
7/12
✓ Branch 0 taken 1778311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1778310 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
1778311 DBUG_EXECUTE_IF("wait_in_the_middle_of_trx", {
7519 /*
7520 See `gr_flush_relay_log_no_split_trx.test`
7521 1) Add a debug sync point that holds and makes the applier thread to
7522 wait, in the middle of a transaction -
7523 `signal.rpl_requested_for_a_flush`.
7524 */
7525 DBUG_SET("-d,wait_in_the_middle_of_trx");
7526 const char dbug_wait[] = "now WAIT_FOR signal.rpl_requested_for_a_flush";
7527 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(dbug_wait)));
7528 });
7529
7530 /*
7531 inside get_master_version_and_clock()
7532 Show-up of FD:s affects checksum_alg at once because
7533 that changes FD_queue.
7534 */
7535 1778311 enum_binlog_checksum_alg checksum_alg =
7536 1778311 mi->checksum_alg_before_fd != binary_log::BINLOG_CHECKSUM_ALG_UNDEF
7537
2/2
✓ Branch 0 taken 236975 times.
✓ Branch 1 taken 1541336 times.
1778311 ? mi->checksum_alg_before_fd
7538 1541336 : mi->rli->relay_log.relay_log_checksum_alg;
7539
7540 1778311 const char *save_buf =
7541 nullptr; // needed for checksumming the fake Rotate event
7542 char rot_buf[LOG_EVENT_HEADER_LEN + Binary_log_event::ROTATE_HEADER_LEN +
7543 FN_REFLEN];
7544 1778311 Gtid gtid = {0, 0};
7545 1778311 ulonglong immediate_commit_timestamp = 0;
7546 1778311 ulonglong original_commit_timestamp = 0;
7547 1778311 bool info_error{false};
7548 1778311 binary_log::Log_event_basic_info log_event_info;
7549 1778311 ulonglong compressed_transaction_bytes = 0;
7550 1778311 ulonglong uncompressed_transaction_bytes = 0;
7551 1778311 auto compression_type = binary_log::transaction::compression::type::NONE;
7552 1778311 Log_event_type event_type =
7553 1778311 (Log_event_type) static_cast<uchar>(buf[EVENT_TYPE_OFFSET]);
7554
7555
4/6
✓ Branch 0 taken 1555732 times.
✓ Branch 1 taken 222579 times.
✓ Branch 2 taken 1555732 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1555732 times.
1778311 assert(checksum_alg == binary_log::BINLOG_CHECKSUM_ALG_OFF ||
7556 checksum_alg == binary_log::BINLOG_CHECKSUM_ALG_UNDEF ||
7557 checksum_alg == binary_log::BINLOG_CHECKSUM_ALG_CRC32);
7558
7559
1/2
✓ Branch 0 taken 1778311 times.
✗ Branch 1 not taken.
1778311 DBUG_TRACE;
7560
7561 /*
7562 Pause the IO thread execution and wait for 'continue_queuing_event'
7563 signal to continue IO thread execution.
7564 */
7565
4/6
✓ Branch 0 taken 1778311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 162 times.
✓ Branch 3 taken 1778149 times.
✓ Branch 4 taken 162 times.
✗ Branch 5 not taken.
1778311 DBUG_EXECUTE_IF("pause_on_queuing_event",
7566 { rpl_replica_debug_point(DBUG_RPL_S_PAUSE_QUEUING); };);
7567
7568 /*
7569 FD_queue checksum alg description does not apply in a case of
7570 FD itself. The one carries both parts of the checksum data.
7571 */
7572
2/2
✓ Branch 0 taken 13209 times.
✓ Branch 1 taken 1765102 times.
1778311 if (event_type == binary_log::FORMAT_DESCRIPTION_EVENT) {
7573
1/2
✓ Branch 0 taken 13209 times.
✗ Branch 1 not taken.
13209 checksum_alg = Log_event_footer::get_checksum_alg(buf, event_len);
7574 }
7575
7576 // does not hold always because of old binlog can work with NM
7577 // assert(checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF);
7578
7579 // should hold unless manipulations with RL. Tests that do that
7580 // will have to refine the clause.
7581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1778311 times.
1778311 assert(mi->rli->relay_log.relay_log_checksum_alg !=
7582 binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
7583
7584 // Emulate the network corruption
7585
9/18
✓ Branch 0 taken 1778311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1778308 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
1778311 DBUG_EXECUTE_IF(
7586 "corrupt_queue_event",
7587 if (event_type != binary_log::FORMAT_DESCRIPTION_EVENT &&
7588 event_type != binary_log::START_5_7_ENCRYPTION_EVENT) {
7589 char *debug_event_buf_c = const_cast<char *>(buf);
7590 int debug_cor_pos = rand() % (event_len - BINLOG_CHECKSUM_LEN);
7591 debug_event_buf_c[debug_cor_pos] = ~debug_event_buf_c[debug_cor_pos];
7592 DBUG_PRINT("info",
7593 ("Corrupt the event at queue_event: byte on position %d",
7594 debug_cor_pos));
7595 DBUG_SET("");
7596 });
7597 1778311 binary_log_debug::debug_checksum_test =
7598
1/2
✓ Branch 0 taken 1778311 times.
✗ Branch 1 not taken.
1778311 DBUG_EVALUATE_IF("simulate_checksum_test_failure", true, false);
7599
3/4
✓ Branch 0 taken 1778311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1778304 times.
1778311 if (Log_event_footer::event_checksum_test(
7600 1778311 const_cast<uchar *>(pointer_cast<const uchar *>(buf)), event_len,
7601 checksum_alg)) {
7602
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 mi->report(ERROR_LEVEL, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE, "%s",
7603
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 ER_THD(current_thd, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE));
7604 7 goto err;
7605 }
7606
7607 /*
7608 From now, and up to finishing queuing the event, no other thread is allowed
7609 to write to the relay log, or to rotate it.
7610 */
7611
1/2
✓ Branch 0 taken 1778304 times.
✗ Branch 1 not taken.
1778304 mysql_mutex_lock(log_lock);
7612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1778304 times.
1778304 assert(lock_count == 0);
7613 1778304 lock_count = 1;
7614
7615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1778304 times.
1778304 if (mi->get_mi_description_event() == nullptr) {
7616 LogErr(ERROR_LEVEL, ER_RPL_SLAVE_QUEUE_EVENT_FAILED_INVALID_CONFIGURATION,
7617 mi->get_channel());
7618 goto err;
7619 }
7620
7621 /*
7622 Simulate an unknown ignorable log event by rewriting a Xid
7623 log event before queuing it into relay log.
7624 */
7625
8/12
✓ Branch 0 taken 1778304 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 1778288 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
1778304 DBUG_EXECUTE_IF(
7626 "simulate_unknown_ignorable_log_event_with_xid",
7627 if (event_type == binary_log::XID_EVENT) {
7628 uchar *ev_buf = const_cast<uchar *>(pointer_cast<const uchar *>(buf));
7629 /* Overwrite the log event type with an unknown type. */
7630 ev_buf[EVENT_TYPE_OFFSET] = binary_log::ENUM_END_EVENT + 1;
7631 /* Set LOG_EVENT_IGNORABLE_F for the log event. */
7632 int2store(ev_buf + FLAGS_OFFSET,
7633 uint2korr(ev_buf + FLAGS_OFFSET) | LOG_EVENT_IGNORABLE_F);
7634 /* Recalc event's CRC */
7635 ha_checksum ev_crc = checksum_crc32(0L, nullptr, 0);
7636 ev_crc = checksum_crc32(ev_crc, (const uchar *)ev_buf,
7637 event_len - BINLOG_CHECKSUM_LEN);
7638 int4store(&ev_buf[event_len - BINLOG_CHECKSUM_LEN], ev_crc);
7639 /*
7640 We will skip writing this event to the relay log in order to let
7641 the startup procedure to not finding it and assuming this transaction
7642 is incomplete.
7643 But we have to keep the unknown ignorable error to let the
7644 "stop_io_after_reading_unknown_event" debug point to work after
7645 "queuing" this event.
7646 */
7647 mysql_mutex_lock(&mi->data_lock);
7648 mi->set_master_log_pos(mi->get_master_log_pos() + event_len);
7649 lock_count = 2;
7650 goto end;
7651 });
7652
7653 /*
7654 This transaction parser is used to ensure that the GTID of the transaction
7655 (if it has one) will only be added to the Retrieved_Gtid_Set after the
7656 last event of the transaction be queued.
7657 It will also be used to avoid rotating the relay log in the middle of
7658 a transaction.
7659 */
7660
1/2
✓ Branch 0 taken 1778302 times.
✗ Branch 1 not taken.
1778302 std::tie(info_error, log_event_info) = extract_log_event_basic_info(
7661 3556604 buf, event_len, mi->get_mi_description_event());
7662
6/8
✓ Branch 0 taken 1778302 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1778302 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 1778283 times.
✓ Branch 6 taken 19 times.
✓ Branch 7 taken 1778283 times.
1778302 if (info_error || mi->transaction_parser.feed_event(log_event_info, true)) {
7663 /*
7664 The transaction parser detected a problem while changing state and threw
7665 a warning message. We are taking care of avoiding transaction boundary
7666 issues, but it can happen.
7667
7668 Transaction boundary errors might happen mostly because of bad master
7669 positioning in 'CHANGE MASTER TO' (or bad manipulation of master.info)
7670 when GTID auto positioning is off. Errors can also happen when using
7671 cross-version replication, replicating from a master that supports more
7672 event types than this slave.
7673
7674 The IO thread will keep working and queuing events regardless of the
7675 transaction parser error, but we will throw another warning message to
7676 log the relay log file and position of the parser error to help
7677 forensics.
7678 */
7679
8/16
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 19 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 19 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 19 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 19 times.
✗ Branch 15 not taken.
19 LogErr(WARNING_LEVEL,
7680 ER_RPL_SLAVE_IO_THREAD_DETECTED_UNEXPECTED_EVENT_SEQUENCE,
7681 mi->get_master_log_name(), mi->get_master_log_pos());
7682 }
7683
7684
3/4
✓ Branch 0 taken 1778302 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 282195 times.
✓ Branch 3 taken 1496107 times.
1778302 if (rli->is_row_format_required()) {
7685
3/4
✓ Branch 0 taken 282195 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 282188 times.
564390 if (info_error ||
7686
3/4
✓ Branch 0 taken 282195 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 282188 times.
282195 mi->transaction_parser.check_row_logging_constraints(log_event_info)) {
7687
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
14 mi->report(ERROR_LEVEL,
7688 ER_RPL_SLAVE_QUEUE_EVENT_FAILED_INVALID_NON_ROW_FORMAT,
7689
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 ER_THD(current_thd,
7690 ER_RPL_SLAVE_QUEUE_EVENT_FAILED_INVALID_NON_ROW_FORMAT),
7691 mi->get_channel());
7692 7 goto err;
7693 }
7694 }
7695
7696
10/10
✓ Branch 0 taken 226 times.
✓ Branch 1 taken 18914 times.
✓ Branch 2 taken 13209 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 3414 times.
✓ Branch 5 taken 11172 times.
✓ Branch 6 taken 19 times.
✓ Branch 7 taken 58386 times.
✓ Branch 8 taken 270586 times.
✓ Branch 9 taken 1402368 times.
1778295 switch (event_type) {
7697 226 case binary_log::STOP_EVENT:
7698 /*
7699 We needn't write this event to the relay log. Indeed, it just indicates
7700 a master server shutdown. The only thing this does is cleaning. But
7701 cleaning is already done on a per-master-thread basis (as the master
7702 server is shutting down cleanly, it has written all DROP TEMPORARY TABLE
7703 prepared statements' deletion are TODO only when we binlog prep stmts).
7704
7705 We don't even increment mi->get_master_log_pos(), because we may be just
7706 after a Rotate event. Btw, in a few milliseconds we are going to have a
7707 Start event from the next binlog (unless the master is presently running
7708 without --log-bin).
7709 */
7710 226 do_flush_mi = false;
7711 226 goto end;
7712 18914 case binary_log::ROTATE_EVENT: {
7713 18914 Format_description_log_event *fde = mi->get_mi_description_event();
7714 18914 enum_binlog_checksum_alg fde_checksum_alg = fde->footer()->checksum_alg;
7715
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 18910 times.
18914 if (fde_checksum_alg != checksum_alg)
7716 4 fde->footer()->checksum_alg = checksum_alg;
7717
1/2
✓ Branch 0 taken 18914 times.
✗ Branch 1 not taken.
18914 Rotate_log_event rev(buf, fde);
7718 18914 fde->footer()->checksum_alg = fde_checksum_alg;
7719
7720
3/4
✓ Branch 0 taken 18914 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 18910 times.
18914 if (unlikely(process_io_rotate(mi, &rev))) {
7721 // This error will be reported later at handle_slave_io().
7722 4 goto err;
7723 }
7724 /*
7725 Checksum special cases for the fake Rotate (R_f) event caused by the
7726 protocol of events generation and serialization in RL where Rotate of
7727 master is queued right next to FD of slave. Since it's only FD that
7728 carries the alg desc of FD_s has to apply to R_m. Two special rules
7729 apply only to the first R_f which comes in before any FD_m. The 2nd R_f
7730 should be compatible with the FD_s that must have taken over the last
7731 seen FD_m's (A).
7732
7733 RSC_1: If OM \and fake Rotate \and slave is configured to
7734 to compute checksum for its first FD event for RL
7735 the fake Rotate gets checksummed here.
7736 */
7737
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 13210 times.
32139 if (uint4korr(&buf[0]) == 0 &&
7738
4/4
✓ Branch 0 taken 13229 times.
✓ Branch 1 taken 5681 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 18907 times.
32139 checksum_alg == binary_log::BINLOG_CHECKSUM_ALG_OFF &&
7739
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16 times.
19 mi->rli->relay_log.relay_log_checksum_alg !=
7740 binary_log::BINLOG_CHECKSUM_ALG_OFF) {
7741
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ha_checksum rot_crc = checksum_crc32(0L, nullptr, 0);
7742 3 event_len += BINLOG_CHECKSUM_LEN;
7743 3 memcpy(rot_buf, buf, event_len - BINLOG_CHECKSUM_LEN);
7744 3 int4store(&rot_buf[EVENT_LEN_OFFSET],
7745 3 uint4korr(rot_buf + EVENT_LEN_OFFSET) + BINLOG_CHECKSUM_LEN);
7746
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 rot_crc = checksum_crc32(rot_crc, (const uchar *)rot_buf,
7747 event_len - BINLOG_CHECKSUM_LEN);
7748 3 int4store(&rot_buf[event_len - BINLOG_CHECKSUM_LEN], rot_crc);
7749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(event_len == uint4korr(&rot_buf[EVENT_LEN_OFFSET]));
7750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(mi->get_mi_description_event()->common_footer->checksum_alg ==
7751 mi->rli->relay_log.relay_log_checksum_alg);
7752 /* the first one */
7753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(mi->checksum_alg_before_fd !=
7754 binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
7755 3 save_buf = buf;
7756 3 buf = rot_buf;
7757 } else
7758 /*
7759 RSC_2: If NM \and fake Rotate \and slave does not compute checksum
7760 the fake Rotate's checksum is stripped off before relay-logging.
7761 */
7762
2/2
✓ Branch 0 taken 13210 times.
✓ Branch 1 taken 16 times.
32133 if (uint4korr(&buf[0]) == 0 &&
7763
4/4
✓ Branch 0 taken 13226 times.
✓ Branch 1 taken 5681 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 18906 times.
32133 checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF &&
7764
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13209 times.
13210 mi->rli->relay_log.relay_log_checksum_alg ==
7765 binary_log::BINLOG_CHECKSUM_ALG_OFF) {
7766 1 event_len -= BINLOG_CHECKSUM_LEN;
7767 1 memcpy(rot_buf, buf, event_len);
7768 1 int4store(&rot_buf[EVENT_LEN_OFFSET],
7769 1 uint4korr(rot_buf + EVENT_LEN_OFFSET) - BINLOG_CHECKSUM_LEN);
7770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(event_len == uint4korr(&rot_buf[EVENT_LEN_OFFSET]));
7771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(mi->get_mi_description_event()->common_footer->checksum_alg ==
7772 mi->rli->relay_log.relay_log_checksum_alg);
7773 /* the first one */
7774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(mi->checksum_alg_before_fd !=
7775 binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
7776 1 save_buf = buf;
7777 1 buf = rot_buf;
7778 }
7779 /*
7780 Now the I/O thread has just changed its mi->get_master_log_name(), so
7781 incrementing mi->get_master_log_pos() is nonsense.
7782 */
7783 18910 inc_pos = 0;
7784 18910 break;
7785
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 18910 times.
18914 }
7786 13209 case binary_log::FORMAT_DESCRIPTION_EVENT: {
7787 /*
7788 Create an event, and save it (when we rotate the relay log, we will have
7789 to write this event again).
7790 */
7791 /*
7792 We are the only thread which reads/writes mi_description_event.
7793 The relay_log struct does not move (though some members of it can
7794 change), so we needn't any lock (no rli->data_lock, no log lock).
7795 */
7796 // mark it as undefined that is irrelevant anymore
7797 13209 mi->checksum_alg_before_fd = binary_log::BINLOG_CHECKSUM_ALG_UNDEF;
7798 Format_description_log_event *new_fdle;
7799 13209 Log_event *ev = nullptr;
7800
1/2
✓ Branch 0 taken 13209 times.
✗ Branch 1 not taken.
13209 if (binlog_event_deserialize(reinterpret_cast<const unsigned char *>(buf),
7801 13209 event_len, mi->get_mi_description_event(),
7802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13209 times.
13209 true, &ev) != Binlog_read_error::SUCCESS) {
7803 // This error will be reported later at handle_slave_io().
7804 goto err;
7805 }
7806
7807
1/2
✓ Branch 0 taken 13209 times.
✗ Branch 1 not taken.
13209 new_fdle = dynamic_cast<Format_description_log_event *>(ev);
7808
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 13205 times.
13209 if (new_fdle->common_footer->checksum_alg ==
7809 binary_log::BINLOG_CHECKSUM_ALG_UNDEF)
7810 4 new_fdle->common_footer->checksum_alg =
7811 binary_log::BINLOG_CHECKSUM_ALG_OFF;
7812
7813
1/2
✓ Branch 0 taken 13209 times.
✗ Branch 1 not taken.
13209 mi->set_mi_description_event(new_fdle);
7814
7815 /* installing new value of checksum Alg for relay log */
7816 13209 mi->rli->relay_log.relay_log_checksum_alg =
7817 13209 new_fdle->common_footer->checksum_alg;
7818
7819 /*
7820 Though this does some conversion to the slave's format, this will
7821 preserve the master's binlog format version, and number of event types.
7822 */
7823 /*
7824 If the event was not requested by the slave (the slave did not ask for
7825 it), i.e. has end_log_pos=0, we do not increment
7826 mi->get_master_log_pos()
7827 */
7828
2/2
✓ Branch 0 taken 11174 times.
✓ Branch 1 taken 2035 times.
13209 inc_pos = uint4korr(buf + LOG_POS_OFFSET) ? event_len : 0;
7829
3/8
✓ Branch 0 taken 13209 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13209 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 13209 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
13209 DBUG_PRINT("info", ("binlog format is now %d",
7830 mi->get_mi_description_event()->binlog_version));
7831
7832 13209 } break;
7833
7834 1 case binary_log::HEARTBEAT_LOG_EVENT: {
7835 /*
7836 HB (heartbeat) cannot come before RL (Relay)
7837 */
7838
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 Heartbeat_log_event hb(buf, mi->get_mi_description_event());
7839 1 std::string mi_log_filename{mi->get_master_log_name() != nullptr
7840 1 ? mi->get_master_log_name()
7841
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 : ""};
7842
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if (heartbeat_queue_event(hb.is_valid(), mi, mi_log_filename,
7843
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 hb.header()->log_pos, inc_pos, do_flush_mi))
7844 goto err;
7845 else
7846 1 goto end;
7847
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
2 } break;
7848
7849 3414 case binary_log::HEARTBEAT_LOG_EVENT_V2: {
7850 /*
7851 HB (heartbeat) cannot come before RL (Relay)
7852 */
7853
1/2
✓ Branch 0 taken 3414 times.
✗ Branch 1 not taken.
3414 Heartbeat_log_event_v2 hb(buf, mi->get_mi_description_event());
7854
1/2
✓ Branch 0 taken 3414 times.
✗ Branch 1 not taken.
3414 auto hb_log_filename = hb.get_log_filename();
7855
2/4
✓ Branch 0 taken 3414 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3414 times.
3414 auto hb_log_position = hb.get_log_position() == 0 ? hb.header()->log_pos
7856
1/2
✓ Branch 0 taken 3414 times.
✗ Branch 1 not taken.
3414 : hb.get_log_position();
7857 3414 std::string mi_log_filename{mi->get_master_log_name() != nullptr
7858 3414 ? mi->get_master_log_name()
7859
2/4
✓ Branch 0 taken 3414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3414 times.
✗ Branch 3 not taken.
6828 : ""};
7860
4/8
✓ Branch 0 taken 3414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3414 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3414 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3414 times.
3414 if (heartbeat_queue_event(hb.is_valid(), mi, mi_log_filename,
7861 hb_log_position, inc_pos, do_flush_mi))
7862 goto err;
7863 else
7864 3414 goto end;
7865
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3414 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3414 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3414 times.
10242 } break;
7866 11172 case binary_log::PREVIOUS_GTIDS_LOG_EVENT: {
7867 /*
7868 This event does not have any meaning for the slave and
7869 was just sent to show the slave the master is making
7870 progress and avoid possible deadlocks.
7871 So at this point, the event is replaced by a rotate
7872 event what will make the slave to update what it knows
7873 about the master's coordinates.
7874 */
7875 11172 inc_pos = 0;
7876
1/2
✓ Branch 0 taken 11172 times.
✗ Branch 1 not taken.
11172 mysql_mutex_lock(&mi->data_lock);
7877 11172 mi->set_master_log_pos(mi->get_master_log_pos() + event_len);
7878
1/2
✓ Branch 0 taken 11172 times.
✗ Branch 1 not taken.
11172 mysql_mutex_unlock(&mi->data_lock);
7879
7880
2/4
✓ Branch 0 taken 11172 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11172 times.
11172 if (write_rotate_to_master_pos_into_relay_log(
7881 mi->info_thd, mi, true /* force_flush_mi_info */))
7882 goto err;
7883
7884 11172 do_flush_mi = false; /* write_rotate_... above flushed master info */
7885 11172 goto end;
7886 } break;
7887
7888 19 case binary_log::TRANSACTION_PAYLOAD_EVENT: {
7889 binary_log::Transaction_payload_event tpe(buf,
7890
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 mi->get_mi_description_event());
7891 19 compression_type = tpe.get_compression_type();
7892 19 compressed_transaction_bytes = tpe.get_payload_size();
7893 19 uncompressed_transaction_bytes = tpe.get_uncompressed_size();
7894 19 auto gtid_monitoring_info = mi->get_gtid_monitoring_info();
7895
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 gtid_monitoring_info->update(compression_type,
7896 compressed_transaction_bytes,
7897 uncompressed_transaction_bytes);
7898 19 inc_pos = event_len;
7899 19 break;
7900 19 }
7901
7902 58386 case binary_log::GTID_LOG_EVENT: {
7903 /*
7904 This can happen if the master uses GTID_MODE=OFF_PERMISSIVE, and
7905 sends GTID events to the slave. A possible scenario is that user
7906 does not follow the upgrade procedure for GTIDs, and creates a
7907 topology like A->B->C, where A uses GTID_MODE=ON_PERMISSIVE, B
7908 uses GTID_MODE=OFF_PERMISSIVE, and C uses GTID_MODE=OFF. Each
7909 connection is allowed, but the master A will generate GTID
7910 transactions which will be sent through B to C. Then C will hit
7911 this error.
7912 */
7913
3/4
✓ Branch 0 taken 58386 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 58383 times.
58386 if (global_gtid_mode.get() == Gtid_mode::OFF) {
7914
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 mi->report(
7915 ERROR_LEVEL, ER_CANT_REPLICATE_GTID_WITH_GTID_MODE_OFF,
7916
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 ER_THD(current_thd, ER_CANT_REPLICATE_GTID_WITH_GTID_MODE_OFF),
7917 mi->get_master_log_name(), mi->get_master_log_pos());
7918 3 goto err;
7919 }
7920
1/2
✓ Branch 0 taken 58383 times.
✗ Branch 1 not taken.
58383 Gtid_log_event gtid_ev(buf, mi->get_mi_description_event());
7921
2/4
✓ Branch 0 taken 58383 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 58383 times.
58383 if (!gtid_ev.is_valid()) goto err;
7922
1/2
✓ Branch 0 taken 58383 times.
✗ Branch 1 not taken.
58383 rli->get_sid_lock()->rdlock();
7923
1/2
✓ Branch 0 taken 58383 times.
✗ Branch 1 not taken.
58383 gtid.sidno = gtid_ev.get_sidno(rli->get_gtid_set()->get_sid_map());
7924
1/2
✓ Branch 0 taken 58383 times.
✗ Branch 1 not taken.
58383 rli->get_sid_lock()->unlock();
7925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58383 times.
58383 if (gtid.sidno < 0) goto err;
7926 58383 gtid.gno = gtid_ev.get_gno();
7927 58383 original_commit_timestamp = gtid_ev.original_commit_timestamp;
7928 58383 immediate_commit_timestamp = gtid_ev.immediate_commit_timestamp;
7929 58383 compressed_transaction_bytes = uncompressed_transaction_bytes =
7930
1/2
✓ Branch 0 taken 58383 times.
✗ Branch 1 not taken.
58383 gtid_ev.transaction_length - gtid_ev.get_event_length();
7931
7932 58383 inc_pos = event_len;
7933
1/2
✓ Branch 0 taken 58383 times.
✗ Branch 1 not taken.
116766 } break;
7934
7935 270586 case binary_log::ANONYMOUS_GTID_LOG_EVENT: {
7936 /*
7937 This cannot normally happen, because the master has a check that
7938 prevents it from sending anonymous events when auto_position is
7939 enabled. However, the master could be something else than
7940 mysqld, which could contain bugs that we have no control over.
7941 So we need this check on the slave to be sure that whoever is on
7942 the other side of the protocol does not break the protocol.
7943 */
7944
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 270583 times.
270586 if (mi->is_auto_position()) {
7945
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 mi->report(
7946 ERROR_LEVEL, ER_CANT_REPLICATE_ANONYMOUS_WITH_AUTO_POSITION,
7947
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 ER_THD(current_thd, ER_CANT_REPLICATE_ANONYMOUS_WITH_AUTO_POSITION),
7948 mi->get_master_log_name(), mi->get_master_log_pos());
7949 6 goto err;
7950 }
7951 /*
7952 This can happen if the master uses GTID_MODE=ON_PERMISSIVE, and
7953 sends an anonymous event to the slave. A possible scenario is
7954 that user does not follow the upgrade procedure for GTIDs, and
7955 creates a topology like A->B->C, where A uses
7956 GTID_MODE=OFF_PERMISSIVE, B uses GTID_MODE=ON_PERMISSIVE, and C
7957 uses GTID_MODE=ON. Each connection is allowed, but the master A
7958 will generate anonymous transactions which will be sent through
7959 B to C. Then C will hit this error.
7960 There is a special case where on the slave
7961 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS= LOCAL/UUID in that case it is
7962 possible to replicate from a GTID_MODE=OFF master to a GTID_MODE=ON
7963 slave
7964 */
7965 541166 else if (mi->rli->m_assign_gtids_to_anonymous_transactions_info
7966
3/4
✓ Branch 0 taken 270583 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269949 times.
✓ Branch 3 taken 634 times.
270583 .get_type() == Assign_gtids_to_anonymous_transactions_info::
7967 enum_type::AGAT_OFF) {
7968
3/4
✓ Branch 0 taken 269949 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 269946 times.
269949 if (global_gtid_mode.get() == Gtid_mode::ON) {
7969
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 mi->report(ERROR_LEVEL, ER_CANT_REPLICATE_ANONYMOUS_WITH_GTID_MODE_ON,
7970
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 ER_THD(current_thd,
7971 ER_CANT_REPLICATE_ANONYMOUS_WITH_GTID_MODE_ON),
7972 mi->get_master_log_name(), mi->get_master_log_pos());
7973 3 goto err;
7974 }
7975 }
7976 /*
7977 save the original_commit_timestamp and the immediate_commit_timestamp to
7978 be later used for monitoring
7979 */
7980
1/2
✓ Branch 0 taken 270580 times.
✗ Branch 1 not taken.
270580 Gtid_log_event anon_gtid_ev(buf, mi->get_mi_description_event());
7981 270580 original_commit_timestamp = anon_gtid_ev.original_commit_timestamp;
7982 270580 immediate_commit_timestamp = anon_gtid_ev.immediate_commit_timestamp;
7983 270580 compressed_transaction_bytes = uncompressed_transaction_bytes =
7984
1/2
✓ Branch 0 taken 270580 times.
✗ Branch 1 not taken.
270580 anon_gtid_ev.transaction_length - anon_gtid_ev.get_event_length();
7985 270580 }
7986 [[fallthrough]];
7987 default:
7988 1672948 inc_pos = event_len;
7989 1672948 break;
7990 }
7991
7992 /*
7993 Simulate an unknown ignorable log event by rewriting the write_rows log
7994 event and previous_gtids log event before writing them in relay log.
7995 */
7996
6/8
✓ Branch 0 taken 1763469 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1763461 times.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
1763469 DBUG_EXECUTE_IF(
7997 "simulate_unknown_ignorable_log_event",
7998 if (event_type == binary_log::WRITE_ROWS_EVENT ||
7999 event_type == binary_log::PREVIOUS_GTIDS_LOG_EVENT) {
8000 uchar *event_buf =
8001 const_cast<uchar *>(reinterpret_cast<const uchar *>(buf));
8002 /* Overwrite the log event type with an unknown type. */
8003 event_buf[EVENT_TYPE_OFFSET] = binary_log::ENUM_END_EVENT + 1;
8004 /* Set LOG_EVENT_IGNORABLE_F for the log event. */
8005 int2store(event_buf + FLAGS_OFFSET,
8006 uint2korr(event_buf + FLAGS_OFFSET) | LOG_EVENT_IGNORABLE_F);
8007 });
8008
8009 /*
8010 If this event is originating from this server, don't queue it.
8011 We don't check this for 3.23 events because it's simpler like this; 3.23
8012 will be filtered anyway by the SQL slave thread which also tests the
8013 server id (we must also keep this test in the SQL thread, in case somebody
8014 upgrades a 4.0 slave which has a not-filtered relay log).
8015
8016 ANY event coming from ourselves can be ignored: it is obvious for queries;
8017 for STOP_EVENT/ROTATE_EVENT/START_EVENT: these cannot come from ourselves
8018 (--log-replica-updates would not log that) unless this slave is also its
8019 direct master (an unsupported, useless setup!).
8020 */
8021
8022 1763469 s_id = uint4korr(buf + SERVER_ID_OFFSET);
8023
8024 /*
8025 If server_id_bits option is set we need to mask out irrelevant bits
8026 when checking server_id, but we still put the full unmasked server_id
8027 into the Relay log so that it can be accessed when applying the event
8028 */
8029 1763469 s_id &= opt_server_id_mask;
8030
8031
6/6
✓ Branch 0 taken 23820 times.
✓ Branch 1 taken 1739649 times.
✓ Branch 2 taken 15346 times.
✓ Branch 3 taken 8474 times.
✓ Branch 4 taken 8492 times.
✓ Branch 5 taken 1754977 times.
3518464 if ((s_id == ::server_id && !mi->rli->replicate_same_server_id) ||
8032 /*
8033 the following conjunction deals with IGNORE_SERVER_IDS, if set
8034 If the master is on the ignore list, execution of
8035 format description log events and rotate events is necessary.
8036 */
8037
3/4
✓ Branch 0 taken 1754995 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 1754951 times.
1754995 (mi->ignore_server_ids->dynamic_ids.size() > 0 &&
8038
3/4
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 14 times.
44 mi->shall_ignore_server_id(s_id) &&
8039 /* everything is filtered out from non-master */
8040
3/4
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 6 times.
30 (s_id != mi->master_id ||
8041 /* for the master meta information is necessary */
8042
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
24 (event_type != binary_log::FORMAT_DESCRIPTION_EVENT &&
8043 event_type != binary_log::ROTATE_EVENT)))) {
8044 /*
8045 Do not write it to the relay log.
8046 a) We still want to increment mi->get_master_log_pos(), so that we won't
8047 re-read this event from the master if the slave IO thread is now
8048 stopped/restarted (more efficient if the events we are ignoring are big
8049 LOAD DATA INFILE).
8050 b) We want to record that we are skipping events, for the information of
8051 the slave SQL thread, otherwise that thread may let
8052 rli->group_relay_log_pos stay too small if the last binlog's event is
8053 ignored.
8054 But events which were generated by this slave and which do not exist in
8055 the master's binlog (i.e. Format_desc, Rotate & Stop) should not increment
8056 mi->get_master_log_pos().
8057 If the event is originated remotely and is being filtered out by
8058 IGNORE_SERVER_IDS it increments mi->get_master_log_pos()
8059 as well as rli->group_relay_log_pos.
8060 */
8061
4/6
✓ Branch 0 taken 8474 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 8474 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8474 times.
✗ Branch 5 not taken.
8492 if (!(s_id == ::server_id && !mi->rli->replicate_same_server_id) ||
8062
1/2
✓ Branch 0 taken 8474 times.
✗ Branch 1 not taken.
8474 (event_type != binary_log::FORMAT_DESCRIPTION_EVENT &&
8063
1/2
✓ Branch 0 taken 8474 times.
✗ Branch 1 not taken.
8474 event_type != binary_log::ROTATE_EVENT &&
8064 event_type != binary_log::STOP_EVENT)) {
8065
1/2
✓ Branch 0 taken 8492 times.
✗ Branch 1 not taken.
8492 rli->relay_log.lock_binlog_end_pos();
8066 8492 mi->set_master_log_pos(mi->get_master_log_pos() + inc_pos);
8067 8492 memcpy(rli->ign_master_log_name_end, mi->get_master_log_name(),
8068 FN_REFLEN);
8069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8492 times.
8492 assert(rli->ign_master_log_name_end[0]);
8070 8492 rli->ign_master_log_pos_end = mi->get_master_log_pos();
8071 // the slave SQL thread needs to re-check
8072
1/2
✓ Branch 0 taken 8492 times.
✗ Branch 1 not taken.
8492 rli->relay_log.update_binlog_end_pos(false /*need_lock*/);
8073
1/2
✓ Branch 0 taken 8492 times.
✗ Branch 1 not taken.
8492 rli->relay_log.unlock_binlog_end_pos();
8074 }
8075
3/8
✓ Branch 0 taken 8492 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8492 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8492 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8492 DBUG_PRINT(
8076 "info",
8077 ("master_log_pos: %lu, event originating from %u server, ignored",
8078 (ulong)mi->get_master_log_pos(), uint4korr(buf + SERVER_ID_OFFSET)));
8079 } else {
8080 1754977 bool is_error = false;
8081 /* write the event to the relay log */
8082
3/4
✓ Branch 0 taken 1754977 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1754971 times.
✓ Branch 3 taken 6 times.
1754977 if (likely(rli->relay_log.write_buffer(
8083 reinterpret_cast<uchar *>(const_cast<char *>(buf)),
8084 event_len, mi) == 0)) {
8085
6/10
✓ Branch 0 taken 1754971 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1754965 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
1754971 DBUG_SIGNAL_WAIT_FOR(current_thd,
8086 "pause_on_queue_event_after_write_buffer",
8087 "receiver_reached_pause_on_queue_event",
8088 "receiver_continue_queuing_event");
8089
1/2
✓ Branch 0 taken 1754971 times.
✗ Branch 1 not taken.
1754971 mysql_mutex_lock(&mi->data_lock);
8090 1754971 lock_count = 2;
8091 1754971 mi->set_master_log_pos(mi->get_master_log_pos() + inc_pos);
8092
3/8
✓ Branch 0 taken 1754971 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1754971 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1754971 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1754971 DBUG_PRINT("info",
8093 ("master_log_pos: %lu", (ulong)mi->get_master_log_pos()));
8094
8095 /*
8096 If we are starting an anonymous transaction, we will discard
8097 the GTID of the partial transaction that was not finished (if
8098 there is one) when calling mi->started_queueing().
8099 */
8100 #ifndef NDEBUG
8101
2/2
✓ Branch 0 taken 269092 times.
✓ Branch 1 taken 1485879 times.
1754971 if (event_type == binary_log::ANONYMOUS_GTID_LOG_EVENT) {
8102
3/4
✓ Branch 0 taken 269092 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 269091 times.
269092 if (!mi->get_queueing_trx_gtid()->is_empty()) {
8103
3/12
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1 DBUG_PRINT("info",
8104 ("Discarding Gtid(%d, %" PRId64 ") as the transaction "
8105 "wasn't complete and we found an "
8106 "ANONYMOUS_GTID_LOG_EVENT.",
8107 mi->get_queueing_trx_gtid()->sidno,
8108 mi->get_queueing_trx_gtid()->gno));
8109 }
8110 }
8111 #endif
8112
8113 /*
8114 We have to mark this GTID (either anonymous or not) as started
8115 to be queued.
8116
8117 Also, if this event is a GTID_LOG_EVENT, we have to store its GTID to
8118 add to the Retrieved_Gtid_Set later, when the last event of the
8119 transaction be queued. The call to mi->started_queueing() will save
8120 the GTID to be used later.
8121 */
8122
4/4
✓ Branch 0 taken 1696620 times.
✓ Branch 1 taken 58351 times.
✓ Branch 2 taken 269092 times.
✓ Branch 3 taken 1427528 times.
1754971 if (event_type == binary_log::GTID_LOG_EVENT ||
8123 event_type == binary_log::ANONYMOUS_GTID_LOG_EVENT) {
8124 // set the timestamp for the start time of queueing this transaction
8125
1/2
✓ Branch 0 taken 327443 times.
✗ Branch 1 not taken.
327443 mi->started_queueing(gtid, original_commit_timestamp,
8126 immediate_commit_timestamp);
8127
8128 327443 auto gtid_monitoring_info = mi->get_gtid_monitoring_info();
8129
1/2
✓ Branch 0 taken 327443 times.
✗ Branch 1 not taken.
327443 gtid_monitoring_info->update(
8130 binary_log::transaction::compression::type::NONE,
8131 compressed_transaction_bytes, uncompressed_transaction_bytes);
8132 }
8133 } else {
8134 /*
8135 We failed to write the event and didn't updated slave positions.
8136
8137 We have to "rollback" the transaction parser state, or else, when
8138 restarting the I/O thread without GTID auto positing the parser
8139 would assume the failed event as queued.
8140 */
8141 6 mi->transaction_parser.rollback();
8142 6 is_error = true;
8143 }
8144
8145
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1754973 times.
1754977 if (save_buf != nullptr) buf = save_buf;
8146
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1754971 times.
1754977 if (is_error) {
8147 // This error will be reported later at handle_slave_io().
8148 6 goto err;
8149 }
8150 }
8151 1763463 goto end;
8152
8153 33 err:
8154 33 res = QUEUE_EVENT_ERROR_QUEUING;
8155
8156 1778311 end:
8157
4/4
✓ Branch 0 taken 1778278 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 1543603 times.
✓ Branch 3 taken 234675 times.
1778311 if (res == QUEUE_EVENT_OK && do_flush_mi) {
8158 /*
8159 Take a ride in the already locked LOCK_log to flush master info.
8160
8161 JAG: TODO: Notice that we could only flush master info if we are
8162 not in the middle of a transaction. Having a proper
8163 relay log recovery can allow us to do this.
8164 */
8165
2/2
✓ Branch 0 taken 11006 times.
✓ Branch 1 taken 1532597 times.
1543603 if (lock_count == 1) {
8166
1/2
✓ Branch 0 taken 11006 times.
✗ Branch 1 not taken.
11006 mysql_mutex_lock(&mi->data_lock);
8167 11006 lock_count = 2;
8168 }
8169
8170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1543603 times.
1543603 if (flush_master_info(mi, false /*force*/, lock_count == 0 /*need_lock*/,
8171
2/4
✓ Branch 0 taken 1543603 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1543603 times.
✗ Branch 3 not taken.
1543603 false /*flush_relay_log*/, mi->is_gtid_only_mode()))
8172 res = QUEUE_EVENT_ERROR_FLUSHING_INFO;
8173
3/4
✓ Branch 0 taken 1543603 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57865 times.
✓ Branch 3 taken 1485738 times.
1543603 if (mi->is_gtid_only_mode()) {
8174
1/2
✓ Branch 0 taken 57865 times.
✗ Branch 1 not taken.
57865 mi->update_flushed_relay_log_info();
8175 }
8176 }
8177
3/4
✓ Branch 0 taken 1765979 times.
✓ Branch 1 taken 12332 times.
✓ Branch 2 taken 1765979 times.
✗ Branch 3 not taken.
1778311 if (lock_count >= 2) mysql_mutex_unlock(&mi->data_lock);
8178
3/4
✓ Branch 0 taken 1778304 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1778304 times.
✗ Branch 3 not taken.
1778311 if (lock_count >= 1) mysql_mutex_unlock(log_lock);
8179
3/8
✓ Branch 0 taken 1778311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1778311 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1778311 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1778311 DBUG_PRINT("info", ("queue result: %d", res));
8180 1778311 return res;
8181 1778311 }
8182
8183 /**
8184 Hook to detach the active VIO before closing a connection handle.
8185
8186 The client API might close the connection (and associated data)
8187 in case it encounters a unrecoverable (network) error. This hook
8188 is called from the client code before the VIO handle is deleted
8189 allows the thread to detach the active vio so it does not point
8190 to freed memory.
8191
8192 Other calls to THD::clear_active_vio throughout this module are
8193 redundant due to the hook but are left in place for illustrative
8194 purposes.
8195 */
8196
8197 12497 void slave_io_thread_detach_vio() {
8198 12497 THD *thd = current_thd;
8199
4/4
✓ Branch 0 taken 12015 times.
✓ Branch 1 taken 483 times.
✓ Branch 2 taken 9036 times.
✓ Branch 3 taken 2979 times.
12498 if (thd && thd->slave_thread) thd->clear_active_vio();
8200 12498 }
8201
8202 /*
8203 Set network namespace if channel is using network namespace and connect
8204 to master.
8205
8206 @param thd THD context
8207 @param mysql MYSQL connection handler
8208 @param mi Master info corresponding to this channel.
8209 @param reconnect Reconnect if true
8210 @param suppress_warnings suppress warnings if required.
8211
8212 @retval 0 ok.
8213 @retval 1 not ok.
8214 */
8215 7868 static int connect_to_master_via_namespace(THD *thd, MYSQL *mysql,
8216 Master_info *mi, bool reconnect,
8217 bool suppress_warnings,
8218 const std::string &host,
8219 const uint port) {
8220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7868 times.
7868 if (mi->is_set_network_namespace()) {
8221 #ifdef HAVE_SETNS
8222 if (set_network_namespace(mi->network_namespace)) return 1;
8223 #else
8224 // Network namespace not supported by the platform. Report error.
8225 LogErr(ERROR_LEVEL, ER_NETWORK_NAMESPACES_NOT_SUPPORTED);
8226 return 1;
8227 #endif
8228 // Save default value of network namespace
8229 // Set network namespace before sockets be created
8230 }
8231 7868 int connect_res = connect_to_master(thd, mysql, mi, reconnect,
8232 suppress_warnings, host, port);
8233 // we can get killed during safe_connect
8234 #ifdef HAVE_SETNS
8235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7868 times.
7868 if (mi->is_set_network_namespace()) {
8236 // Restore original network namespace used to be before connection has
8237 // been created
8238 (void)restore_original_network_namespace();
8239 }
8240 #endif
8241 7868 return connect_res;
8242 }
8243
8244 /*
8245 Try to connect until successful or slave killed
8246
8247 SYNPOSIS
8248 safe_connect()
8249 thd Thread handler for slave
8250 mysql MySQL connection handle
8251 mi Replication handle
8252
8253 RETURN
8254 0 ok
8255 # Error
8256 */
8257 7470 static int safe_connect(THD *thd, MYSQL *mysql, Master_info *mi,
8258 const std::string &host, const uint port) {
8259
1/2
✓ Branch 0 taken 7470 times.
✗ Branch 1 not taken.
7470 DBUG_TRACE;
8260
8261
1/2
✓ Branch 0 taken 7470 times.
✗ Branch 1 not taken.
7470 return connect_to_master_via_namespace(thd, mysql, mi,
8262 /*reconnect=*/false,
8263 /*suppress_warnings=*/false, host,
8264 14940 port);
8265 7470 }
8266
8267 8173 int connect_to_master(THD *thd, MYSQL *mysql, Master_info *mi, bool reconnect,
8268 bool suppress_warnings, const std::string &host,
8269 const uint port, bool is_io_thread) {
8270 8173 int last_errno = -2; // impossible error
8271 8173 ulong err_count = 0;
8272 char llbuff[22];
8273 char password[MAX_PASSWORD_LENGTH + 1];
8274 8173 size_t password_size = sizeof(password);
8275
1/2
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
8173 DBUG_TRACE;
8276
1/2
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
8173 set_replica_max_allowed_packet(thd, mysql);
8277 #ifndef NDEBUG
8278 8173 mi->events_until_exit = disconnect_slave_event_count;
8279 #endif
8280 8173 ulong client_flag = CLIENT_REMEMBER_OPTIONS;
8281
8282 /* Always reset public key to remove cached copy */
8283
1/2
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
8173 mysql_reset_server_public_key();
8284
8285
1/2
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
8173 mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&replica_net_timeout);
8286
1/2
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
8173 mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *)&replica_net_timeout);
8287
8288
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 8161 times.
8173 if (mi->bind_addr[0]) {
8289
3/8
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
12 DBUG_PRINT("info", ("bind_addr: %s", mi->bind_addr));
8290
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 mysql_options(mysql, MYSQL_OPT_BIND, mi->bind_addr);
8291 }
8292
8293 /* By default the channel is not configured to use SSL */
8294 8173 enum mysql_ssl_mode ssl_mode = SSL_MODE_DISABLED;
8295
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 8029 times.
8173 if (mi->ssl) {
8296 /* The channel is configured to use SSL */
8297
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 103 times.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
576 mysql_ssl_set(mysql, mi->ssl_key[0] ? mi->ssl_key : nullptr,
8298
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 103 times.
144 mi->ssl_cert[0] ? mi->ssl_cert : nullptr,
8299
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 103 times.
144 mi->ssl_ca[0] ? mi->ssl_ca : nullptr,
8300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 mi->ssl_capath[0] ? mi->ssl_capath : nullptr,
8301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 mi->ssl_cipher[0] ? mi->ssl_cipher : nullptr);
8302
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 mysql_options(mysql, MYSQL_OPT_SSL_CRL,
8303
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 140 times.
144 mi->ssl_crl[0] ? mi->ssl_crl : nullptr);
8304
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 mysql_options(mysql, MYSQL_OPT_TLS_VERSION,
8305
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 113 times.
144 mi->tls_version[0] ? mi->tls_version : nullptr);
8306
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 mysql_options(mysql, MYSQL_OPT_TLS_CIPHERSUITES,
8307
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 12 times.
144 mi->tls_ciphersuites.first
8308 ? nullptr
8309 12 : mi->tls_ciphersuites.second.c_str());
8310
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH,
8311
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 140 times.
144 mi->ssl_crlpath[0] ? mi->ssl_crlpath : nullptr);
8312
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 135 times.
144 if (mi->ssl_verify_server_cert)
8313 9 ssl_mode = SSL_MODE_VERIFY_IDENTITY;
8314
3/4
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 103 times.
135 else if (mi->ssl_ca[0] || mi->ssl_capath[0])
8315 32 ssl_mode = SSL_MODE_VERIFY_CA;
8316 else
8317 103 ssl_mode = SSL_MODE_REQUIRED;
8318 }
8319
1/2
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
8173 mysql_options(mysql, MYSQL_OPT_SSL_MODE, &ssl_mode);
8320
8321
3/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 8150 times.
✓ Branch 2 taken 8173 times.
✗ Branch 3 not taken.
8173 mysql_options(mysql, MYSQL_OPT_COMPRESSION_ALGORITHMS,
8322 opt_replica_compressed_protocol ? COMPRESSION_ALGORITHM_ZLIB
8323 : mi->compression_algorithm);
8324 8173 mysql_options(mysql, MYSQL_OPT_ZSTD_COMPRESSION_LEVEL,
8325
1/2
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
8173 &mi->zstd_compression_level);
8326 /*
8327 If server's default charset is not supported (like utf16, utf32) as client
8328 charset, then set client charset to 'latin1' (default client charset).
8329 */
8330
2/2
✓ Branch 0 taken 8167 times.
✓ Branch 1 taken 6 times.
8173 if (is_supported_parser_charset(default_charset_info))
8331
1/2
✓ Branch 0 taken 8167 times.
✗ Branch 1 not taken.
8167 mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset_info->csname);
8332 else {
8333
8/16
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 6 times.
✗ Branch 15 not taken.
6 LogErr(INFORMATION_LEVEL, ER_RPL_SLAVE_CANT_USE_CHARSET,
8334 default_charset_info->csname, default_client_charset_info->csname);
8335 6 mysql_options(mysql, MYSQL_SET_CHARSET_NAME,
8336
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 default_client_charset_info->csname);
8337 }
8338
8339
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 8112 times.
8173 if (mi->is_start_plugin_auth_configured()) {
8340
3/8
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 61 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
61 DBUG_PRINT("info", ("Slaving is using MYSQL_DEFAULT_AUTH %s",
8341 mi->get_start_plugin_auth()));
8342
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 mysql_options(mysql, MYSQL_DEFAULT_AUTH, mi->get_start_plugin_auth());
8343 }
8344
8345
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 8131 times.
8173 if (mi->is_start_plugin_dir_configured()) {
8346
3/8
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 42 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
42 DBUG_PRINT("info", ("Slaving is using MYSQL_PLUGIN_DIR %s",
8347 mi->get_start_plugin_dir()));
8348
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mysql_options(mysql, MYSQL_PLUGIN_DIR, mi->get_start_plugin_dir());
8349 }
8350 /* Set MYSQL_PLUGIN_DIR in case master asks for an external authentication
8351 plugin */
8352
2/4
✓ Branch 0 taken 8131 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8131 times.
✗ Branch 3 not taken.
8131 else if (opt_plugin_dir_ptr && *opt_plugin_dir_ptr)
8353
1/2
✓ Branch 0 taken 8131 times.
✗ Branch 1 not taken.
8131 mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir_ptr);
8354
8355
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 8159 times.
8173 if (mi->public_key_path[0]) {
8356 /* Set public key path */
8357
3/8
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
14 DBUG_PRINT("info", ("Set master's public key path"));
8358
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 mysql_options(mysql, MYSQL_SERVER_PUBLIC_KEY, mi->public_key_path);
8359 }
8360
8361 /* Get public key from master */
8362
3/8
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8173 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8173 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8173 DBUG_PRINT("info", ("Set preference to get public key from master"));
8363
1/2
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
8173 mysql_options(mysql, MYSQL_OPT_GET_SERVER_PUBLIC_KEY, &mi->get_public_key);
8364
8365
6/6
✓ Branch 0 taken 7868 times.
✓ Branch 1 taken 305 times.
✓ Branch 2 taken 7741 times.
✓ Branch 3 taken 127 times.
✓ Branch 4 taken 7741 times.
✓ Branch 5 taken 432 times.
8173 if (is_io_thread && !mi->is_start_user_configured())
8366
8/16
✓ Branch 0 taken 7741 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7741 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7741 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7741 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7741 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7741 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 7741 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 7741 times.
✗ Branch 15 not taken.
7741 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_INSECURE_CHANGE_MASTER);
8367
8368
2/4
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8173 times.
8173 if (mi->get_password(password, &password_size)) {
8369 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
8370 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
8371 "Unable to configure password when attempting to "
8372 "connect to the master server. Connection attempt "
8373 "terminated.");
8374 return 1;
8375 }
8376
8377 8173 const char *user = mi->get_user();
8378
3/4
✓ Branch 0 taken 8173 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 8150 times.
8173 if (user == nullptr || user[0] == 0) {
8379
2/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
23 mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
8380 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
8381 "Invalid (empty) username when attempting to "
8382 "connect to the master server. Connection attempt "
8383 "terminated.");
8384 23 return 1;
8385 }
8386
8387
1/2
✓ Branch 0 taken 8150 times.
✗ Branch 1 not taken.
8150 mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "mysqld");
8388
1/2
✓ Branch 0 taken 8150 times.
✗ Branch 1 not taken.
8150 mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "_client_role",
8389 "binary_log_listener");
8390
1/2
✓ Branch 0 taken 8150 times.
✗ Branch 1 not taken.
8150 mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
8391 8150 "_client_replication_channel_name", mi->get_channel());
8392
8393
2/2
✓ Branch 0 taken 7845 times.
✓ Branch 1 taken 305 times.
8150 const char *tmp_host = host.empty() ? mi->host : host.c_str();
8394
2/2
✓ Branch 0 taken 7845 times.
✓ Branch 1 taken 305 times.
8150 uint tmp_port = (port == 0) ? mi->port : port;
8395
8396 8150 bool replica_was_killed{false};
8397 8150 bool connected{false};
8398
8399
1/2
✓ Branch 0 taken 9239 times.
✗ Branch 1 not taken.
9239 while (!connected) {
8400
3/4
✓ Branch 0 taken 8883 times.
✓ Branch 1 taken 356 times.
✓ Branch 2 taken 8883 times.
✗ Branch 3 not taken.
9239 replica_was_killed = is_io_thread ? io_slave_killed(thd, mi)
8401
1/2
✓ Branch 0 taken 356 times.
✗ Branch 1 not taken.
356 : monitor_io_replica_killed(thd, mi);
8402
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 9198 times.
9239 if (replica_was_killed) break;
8403
8404
2/2
✓ Branch 0 taken 1150 times.
✓ Branch 1 taken 8048 times.
9198 if (reconnect) {
8405
1/2
✓ Branch 0 taken 1150 times.
✗ Branch 1 not taken.
1150 connected = !mysql_reconnect(mysql);
8406 } else {
8407 // Set this each time mysql_real_connect() is called to make a connection
8408
1/2
✓ Branch 0 taken 8048 times.
✗ Branch 1 not taken.
8048 mysql_extension_set_server_extn(mysql, &mi->server_extn);
8409
8410
1/2
✓ Branch 0 taken 8048 times.
✗ Branch 1 not taken.
8048 connected = mysql_real_connect(mysql, tmp_host, user, password, nullptr,
8411 tmp_port, nullptr, client_flag);
8412 }
8413
2/2
✓ Branch 0 taken 7825 times.
✓ Branch 1 taken 1373 times.
9198 if (connected) break;
8414
8415 /*
8416 SHOW REPLICA STATUS will display the number of retries which
8417 would be real retry counts instead of mi->retry_count for
8418 each connection attempt by 'Last_IO_Error' entry.
8419 */
8420
1/2
✓ Branch 0 taken 1373 times.
✗ Branch 1 not taken.
1373 last_errno = mysql_errno(mysql);
8421 1373 suppress_warnings = false;
8422
2/2
✓ Branch 0 taken 1228 times.
✓ Branch 1 taken 145 times.
1373 if (is_io_thread) {
8423
4/6
✓ Branch 0 taken 1228 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 818 times.
✓ Branch 3 taken 410 times.
✓ Branch 4 taken 1228 times.
✗ Branch 5 not taken.
1228 mi->report(ERROR_LEVEL, last_errno,
8424 "error %s to master '%s@%s:%d'"
8425 " - retry-time: %d retries: %lu message: %s",
8426 (reconnect ? "reconnecting" : "connecting"), mi->get_user(),
8427 tmp_host, tmp_port, mi->connect_retry, err_count + 1,
8428 mysql_error(mysql));
8429 }
8430
8431 /*
8432 By default we try forever. The reason is that failure will trigger
8433 master election, so if the user did not set mi->retry_count we
8434 do not want to have election triggered on the first failure to
8435 connect
8436 */
8437
2/2
✓ Branch 0 taken 284 times.
✓ Branch 1 taken 1089 times.
1373 if (++err_count == mi->retry_count) {
8438
7/8
✓ Branch 0 taken 284 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 175 times.
✓ Branch 3 taken 109 times.
✓ Branch 4 taken 82 times.
✓ Branch 5 taken 93 times.
✓ Branch 6 taken 82 times.
✓ Branch 7 taken 202 times.
284 if (is_network_error(last_errno) && is_io_thread) mi->set_network_error();
8439 284 replica_was_killed = true;
8440 284 break;
8441 }
8442
3/4
✓ Branch 0 taken 1038 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 1089 times.
✗ Branch 3 not taken.
1089 slave_sleep(thd, mi->connect_retry,
8443 is_io_thread ? io_slave_killed : monitor_io_replica_killed, mi);
8444 }
8445
8446
2/2
✓ Branch 0 taken 7825 times.
✓ Branch 1 taken 325 times.
8150 if (!replica_was_killed) {
8447
2/2
✓ Branch 0 taken 7614 times.
✓ Branch 1 taken 211 times.
7825 if (is_io_thread) {
8448
1/2
✓ Branch 0 taken 7614 times.
✗ Branch 1 not taken.
7614 mi->clear_error(); // clear possible left over reconnect error
8449 7614 mi->reset_network_error();
8450 }
8451
8452
2/2
✓ Branch 0 taken 332 times.
✓ Branch 1 taken 7493 times.
7825 if (reconnect) {
8453
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 276 times.
332 if (!suppress_warnings)
8454
10/20
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 56 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 56 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 56 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 56 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 56 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 56 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 56 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 56 times.
✗ Branch 19 not taken.
56 LogErr(
8455 SYSTEM_LEVEL, ER_RPL_SLAVE_CONNECTED_TO_MASTER_REPLICATION_RESUMED,
8456 mi->get_for_channel_str(), mi->get_user(), tmp_host, tmp_port,
8457 mi->get_io_rpl_log_name(), llstr(mi->get_master_log_pos(), llbuff));
8458 } else {
8459
1/2
✓ Branch 0 taken 7493 times.
✗ Branch 1 not taken.
7493 query_logger.general_log_print(thd, COM_CONNECT_OUT, "%s@%s:%d",
8460 mi->get_user(), tmp_host, tmp_port);
8461 }
8462
8463
1/2
✓ Branch 0 taken 7825 times.
✗ Branch 1 not taken.
7825 thd->set_active_vio(mysql->net.vio);
8464 }
8465 8150 mysql->reconnect = true;
8466
3/8
✓ Branch 0 taken 8150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8150 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8150 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8150 DBUG_PRINT("exit", ("replica_was_killed: %d", replica_was_killed));
8467 8150 return replica_was_killed;
8468 8173 }
8469
8470 /*
8471 safe_reconnect()
8472
8473 IMPLEMENTATION
8474 Try to connect until successful or slave killed or we have retried
8475 mi->retry_count times
8476 */
8477
8478 398 static int safe_reconnect(THD *thd, MYSQL *mysql, Master_info *mi,
8479 bool suppress_warnings, const std::string &host,
8480 const uint port) {
8481
1/2
✓ Branch 0 taken 398 times.
✗ Branch 1 not taken.
398 DBUG_TRACE;
8482
1/2
✓ Branch 0 taken 398 times.
✗ Branch 1 not taken.
398 return connect_to_master_via_namespace(thd, mysql, mi,
8483 /*reconnect=*/true, suppress_warnings,
8484 796 host, port);
8485 398 }
8486
8487 /*
8488 Rotate a relay log (this is used only by FLUSH LOGS; the automatic rotation
8489 because of size is simpler because when we do it we already have all relevant
8490 locks; here we don't, so this function is mainly taking locks).
8491 Returns nothing as we cannot catch any error (MYSQL_BIN_LOG::new_file()
8492 is void).
8493 */
8494
8495 24085 int rotate_relay_log(Master_info *mi, bool log_master_fd, bool need_lock,
8496 bool need_log_space_lock) {
8497
1/2
✓ Branch 0 taken 24085 times.
✗ Branch 1 not taken.
24085 DBUG_TRACE;
8498
8499 24085 Relay_log_info *rli = mi->rli;
8500
8501
2/2
✓ Branch 0 taken 5171 times.
✓ Branch 1 taken 18914 times.
24085 if (need_lock)
8502
1/2
✓ Branch 0 taken 5171 times.
✗ Branch 1 not taken.
5171 mysql_mutex_lock(rli->relay_log.get_log_lock());
8503 else
8504 18914 mysql_mutex_assert_owner(rli->relay_log.get_log_lock());
8505
4/6
✓ Branch 0 taken 24085 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 24079 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
24085 DBUG_EXECUTE_IF("crash_before_rotate_relaylog", DBUG_SUICIDE(););
8506
8507 24079 int error = 0;
8508
8509 /*
8510 We need to test inited because otherwise, new_file() will attempt to lock
8511 LOCK_log, which may not be inited (if we're not a slave).
8512 */
8513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24079 times.
24079 if (!rli->inited) {
8514 DBUG_PRINT("info", ("rli->inited == 0"));
8515 goto end;
8516 }
8517
8518 /* If the relay log is closed, new_file() will do nothing. */
8519
2/2
✓ Branch 0 taken 5165 times.
✓ Branch 1 taken 18914 times.
24079 if (log_master_fd)
8520 error =
8521
1/2
✓ Branch 0 taken 5165 times.
✗ Branch 1 not taken.
5165 rli->relay_log.new_file_without_locking(mi->get_mi_description_event());
8522 else
8523
1/2
✓ Branch 0 taken 18914 times.
✗ Branch 1 not taken.
18914 error = rli->relay_log.new_file_without_locking(nullptr);
8524
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24075 times.
24079 if (error != 0) goto end;
8525
8526 /*
8527 We harvest now, because otherwise BIN_LOG_HEADER_SIZE will not immediately
8528 be counted, so imagine a succession of FLUSH LOGS and assume the slave
8529 threads are started:
8530 relay_log_space decreases by the size of the deleted relay log, but does
8531 not increase, so flush-after-flush we may become negative, which is wrong.
8532 Even if this will be corrected as soon as a query is replicated on the
8533 slave (because the I/O thread will then call harvest_bytes_written() which
8534 will harvest all these BIN_LOG_HEADER_SIZE we forgot), it may give strange
8535 output in SHOW REPLICA STATUS meanwhile. So we harvest now.
8536 If the log is closed, then this will just harvest the last writes, probably
8537 0 as they probably have been harvested.
8538 */
8539
1/2
✓ Branch 0 taken 24075 times.
✗ Branch 1 not taken.
24075 rli->relay_log.harvest_bytes_written(rli, need_log_space_lock);
8540 24079 end:
8541
3/4
✓ Branch 0 taken 5165 times.
✓ Branch 1 taken 18914 times.
✓ Branch 2 taken 5165 times.
✗ Branch 3 not taken.
24079 if (need_lock) mysql_mutex_unlock(rli->relay_log.get_log_lock());
8542 24079 return error;
8543 24079 }
8544
8545 /**
8546 flushes the relay logs of a replication channel.
8547
8548 @param[in] mi Master_info corresponding to the
8549 channel.
8550 @param[in] thd the client thread carrying the command.
8551
8552 @retval 1 fail
8553 @retval 0 ok
8554 @retval -1 deferred flush
8555 */
8556 6694 int flush_relay_logs(Master_info *mi, THD *thd) {
8557
1/2
✓ Branch 0 taken 6694 times.
✗ Branch 1 not taken.
6694 DBUG_TRACE;
8558 6694 int error = 0;
8559
8560
1/2
✓ Branch 0 taken 6694 times.
✗ Branch 1 not taken.
6694 if (mi) {
8561 6694 Relay_log_info *rli = mi->rli;
8562
2/2
✓ Branch 0 taken 5140 times.
✓ Branch 1 taken 1554 times.
6694 if (rli->inited) {
8563 // Rotate immediately if one is true:
8564
1/2
✓ Branch 0 taken 5140 times.
✗ Branch 1 not taken.
5140 if ((!is_group_replication_plugin_loaded() || // GR is disabled
8565
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4790 times.
4792 !mi->transaction_parser
8566 4792 .is_inside_transaction() || // not inside a transaction
8567
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 !channel_map.is_group_replication_channel_name(
8568
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 mi->get_channel(), true) || // channel isn't GR applier channel
8569
4/4
✓ Branch 0 taken 4792 times.
✓ Branch 1 taken 348 times.
✓ Branch 2 taken 5139 times.
✓ Branch 3 taken 1 times.
10282 !mi->slave_running) && // the I/O thread isn't running
8570
6/8
✓ Branch 0 taken 5140 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 5137 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
5140 DBUG_EVALUATE_IF("deferred_flush_relay_log",
8571 !channel_map.is_group_replication_channel_name(
8572 mi->get_channel(), true),
8573 true)) {
8574
2/4
✓ Branch 0 taken 5133 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5133 times.
5139 if (rotate_relay_log(mi)) error = 1;
8575 }
8576 // Postpone the rotate action, delegating it to the I/O thread
8577 else {
8578
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 channel_map.unlock();
8579
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mi->request_rotate(thd);
8580
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 channel_map.rdlock();
8581 1 error = -1;
8582 }
8583 }
8584 }
8585 6688 return error;
8586 6688 }
8587
8588 /**
8589 Entry point for FLUSH RELAYLOGS command or to flush relaylogs for
8590 the FLUSH LOGS command.
8591 FLUSH LOGS or FLUSH RELAYLOGS needs to flush the relaylogs of all
8592 the replciaiton channels in multisource replication.
8593 FLUSH RELAYLOGS FOR CHANNEL flushes only the relaylogs pertaining to
8594 a channel.
8595
8596 @param[in] thd the client thread carrying the command.
8597
8598 @retval true fail
8599 @retval false success
8600 */
8601 1834 bool flush_relay_logs_cmd(THD *thd) {
8602
1/2
✓ Branch 0 taken 1834 times.
✗ Branch 1 not taken.
1834 DBUG_TRACE;
8603 1834 Master_info *mi = nullptr;
8604 1834 LEX *lex = thd->lex;
8605 1834 bool error = false;
8606
8607
1/2
✓ Branch 0 taken 1834 times.
✗ Branch 1 not taken.
1834 channel_map.rdlock();
8608
8609 /*
8610 lex->mi.channel is NULL, for FLUSH LOGS or when the client thread
8611 is not present. (See tmp_thd in the caller).
8612 When channel is not provided, lex->mi.for_channel is false.
8613 */
8614
4/4
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 1720 times.
✓ Branch 2 taken 89 times.
✓ Branch 3 taken 25 times.
1834 if (!lex->mi.channel || !lex->mi.for_channel) {
8615 1809 bool flush_was_deferred{false};
8616 1809 enum_channel_type channel_types[] = {SLAVE_REPLICATION_CHANNEL,
8617 GROUP_REPLICATION_CHANNEL};
8618
8619
2/2
✓ Branch 0 taken 3612 times.
✓ Branch 1 taken 1803 times.
5415 for (auto channel_type : channel_types) {
8620 3612 mi_map already_processed;
8621
8622
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3606 times.
3607 do {
8623 3613 flush_was_deferred = false;
8624
8625
1/2
✓ Branch 0 taken 3613 times.
✗ Branch 1 not taken.
3613 for (mi_map::iterator it = channel_map.begin(channel_type);
8626
3/4
✓ Branch 0 taken 5507 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1901 times.
✓ Branch 3 taken 3606 times.
5507 it != channel_map.end(channel_type); it++) {
8627
3/4
✓ Branch 0 taken 1901 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1900 times.
1901 if (already_processed.find(it->first) != already_processed.end())
8628 1 continue;
8629
8630 1900 mi = it->second;
8631
2/4
✓ Branch 0 taken 1900 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1900 times.
✗ Branch 3 not taken.
1900 already_processed.insert(std::make_pair(it->first, mi));
8632
8633
1/2
✓ Branch 0 taken 1894 times.
✗ Branch 1 not taken.
1900 int flush_status = flush_relay_logs(mi, thd);
8634 1894 flush_was_deferred = (flush_status == -1);
8635 1894 error = (flush_status == 1);
8636
8637
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1893 times.
1894 if (flush_status != 0) break;
8638 }
8639 } while (flush_was_deferred);
8640 3606 }
8641 1803 } else {
8642
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 mi = channel_map.get_mi(lex->mi.channel);
8643
8644
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 6 times.
25 if (mi) {
8645
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 error = (flush_relay_logs(mi, thd) == 1);
8646 } else {
8647
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL ||
8648
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 thd->system_thread == SYSTEM_THREAD_SLAVE_WORKER) {
8649 /*
8650 Log warning on SQL or worker threads.
8651 */
8652
8/16
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
2 LogErr(WARNING_LEVEL, ER_RPL_SLAVE_INCORRECT_CHANNEL, lex->mi.channel);
8653 } else {
8654 /*
8655 Return error on client sessions.
8656 */
8657 4 error = true;
8658
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_SLAVE_CHANNEL_DOES_NOT_EXIST, MYF(0), lex->mi.channel);
8659 }
8660 }
8661 }
8662
8663
1/2
✓ Branch 0 taken 1828 times.
✗ Branch 1 not taken.
1828 channel_map.unlock();
8664
8665 1828 return error;
8666 1828 }
8667
8668 66 bool reencrypt_relay_logs() {
8669
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 DBUG_TRACE;
8670
8671 Master_info *mi;
8672
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 channel_map.rdlock();
8673
8674 66 enum_channel_type channel_types[] = {SLAVE_REPLICATION_CHANNEL,
8675 GROUP_REPLICATION_CHANNEL};
8676
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 63 times.
192 for (auto channel_type : channel_types) {
8677
1/2
✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
129 for (mi_map::iterator it = channel_map.begin(channel_type);
8678
3/4
✓ Branch 0 taken 192 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
✓ Branch 3 taken 126 times.
192 it != channel_map.end(channel_type); it++) {
8679 66 mi = it->second;
8680
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if (mi != nullptr) {
8681 66 Relay_log_info *rli = mi->rli;
8682
8/10
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 58 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 63 times.
66 if (rli != nullptr && rli->inited && rli->relay_log.reencrypt_logs()) {
8683
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 channel_map.unlock();
8684 3 return true;
8685 }
8686 }
8687 }
8688 }
8689
8690
1/2
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
63 channel_map.unlock();
8691
8692 63 return false;
8693 66 }
8694
8695 /**
8696 Detects, based on master's version (as found in the relay log), if master
8697 has a certain bug.
8698 @param rli Relay_log_info which tells the master's version
8699 @param bug_id Number of the bug as found in bugs.mysql.com
8700 @param report bool report error message, default true
8701
8702 @param pred Predicate function that will be called with @c param to
8703 check for the bug. If the function return @c true, the bug is present,
8704 otherwise, it is not.
8705
8706 @param param State passed to @c pred function.
8707
8708 @return true if master has the bug, false if it does not.
8709 */
8710 43630 bool rpl_master_has_bug(const Relay_log_info *rli, uint bug_id, bool report,
8711 bool (*pred)(const void *), const void *param) {
8712 struct st_version_range_for_one_bug {
8713 uint bug_id;
8714 const uchar introduced_in[3]; // first version with bug
8715 const uchar fixed_in[3]; // first version with fix
8716 };
8717 static struct st_version_range_for_one_bug versions_for_all_bugs[] = {
8718 {24432, {5, 0, 24}, {5, 0, 38}}, {24432, {5, 1, 12}, {5, 1, 17}},
8719 {33029, {5, 0, 0}, {5, 0, 58}}, {33029, {5, 1, 0}, {5, 1, 12}},
8720 {37426, {5, 1, 0}, {5, 1, 26}},
8721 };
8722 const uchar *master_ver =
8723 43630 rli->get_rli_description_event()->server_version_split;
8724
8725 assert(sizeof(rli->get_rli_description_event()->server_version_split) == 3);
8726
8727 261763 for (uint i = 0;
8728
2/2
✓ Branch 0 taken 218138 times.
✓ Branch 1 taken 43625 times.
261763 i < sizeof(versions_for_all_bugs) / sizeof(*versions_for_all_bugs);
8729 i++) {
8730 218138 const uchar *introduced_in = versions_for_all_bugs[i].introduced_in,
8731 218138 *fixed_in = versions_for_all_bugs[i].fixed_in;
8732 523195 if ((versions_for_all_bugs[i].bug_id == bug_id) &&
8733
2/2
✓ Branch 0 taken 86805 times.
✓ Branch 1 taken 114 times.
86919 (memcmp(introduced_in, master_ver, 3) <= 0) &&
8734
8/8
✓ Branch 0 taken 86919 times.
✓ Branch 1 taken 131219 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 86796 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 218133 times.
305062 (memcmp(fixed_in, master_ver, 3) > 0) &&
8735
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 (pred == nullptr || (*pred)(param))) {
8736
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (!report) return true;
8737 // a short message for SHOW REPLICA STATUS (message length constraints)
8738 3 my_printf_error(ER_UNKNOWN_ERROR,
8739 "master may suffer from"
8740 " http://bugs.mysql.com/bug.php?id=%u"
8741 " so slave stops; check error log on slave"
8742 " for more info",
8743 MYF(0), bug_id);
8744 // a verbose message for the error log
8745 3 enum loglevel report_level = INFORMATION_LEVEL;
8746
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!ignored_error_code(ER_UNKNOWN_ERROR)) {
8747 3 report_level = ERROR_LEVEL;
8748 3 current_thd->is_slave_error = true;
8749 } else if (log_error_verbosity >= 2)
8750 report_level = WARNING_LEVEL;
8751
8752
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (report_level != INFORMATION_LEVEL)
8753 6 rli->report(report_level, ER_SERVER_UNKNOWN_ERROR,
8754 "According to the master's version ('%s'),"
8755 " it is probable that master suffers from this bug:"
8756 " http://bugs.mysql.com/bug.php?id=%u"
8757 " and thus replicating the current binary log event"
8758 " may make the slave's data become different from the"
8759 " master's data."
8760 " To take no risk, slave refuses to replicate"
8761 " this event and stops."
8762 " We recommend that all updates be stopped on the"
8763 " master and slave, that the data of both be"
8764 " manually synchronized,"
8765 " that master's binary logs be deleted,"
8766 " that master be upgraded to a version at least"
8767 " equal to '%d.%d.%d'. Then replication can be"
8768 " restarted.",
8769 3 rli->get_rli_description_event()->server_version, bug_id,
8770 3 fixed_in[0], fixed_in[1], fixed_in[2]);
8771 3 return true;
8772 }
8773 }
8774 43625 return false;
8775 }
8776
8777 /**
8778 BUG#33029, For all 5.0 up to 5.0.58 exclusive, and 5.1 up to 5.1.12
8779 exclusive, if one statement in a SP generated AUTO_INCREMENT value
8780 by the top statement, all statements after it would be considered
8781 generated AUTO_INCREMENT value by the top statement, and a
8782 erroneous INSERT_ID value might be associated with these statement,
8783 which could cause duplicate entry error and stop the slave.
8784
8785 Detect buggy master to work around.
8786 */
8787 695532 bool rpl_master_erroneous_autoinc(THD *thd) {
8788
3/4
✓ Branch 0 taken 43266 times.
✓ Branch 1 taken 652266 times.
✓ Branch 2 taken 43266 times.
✗ Branch 3 not taken.
695532 if (thd->rli_slave && thd->rli_slave->info_thd == thd) {
8789 43266 Relay_log_info *c_rli = thd->rli_slave->get_c_rli();
8790
8791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43266 times.
43266 DBUG_EXECUTE_IF("simulate_bug33029", return true;);
8792 43266 return rpl_master_has_bug(c_rli, 33029, false, nullptr, nullptr);
8793 }
8794 652266 return false;
8795 }
8796
8797 /**
8798 a copy of active_mi->rli->slave_skip_counter, for showing in SHOW GLOBAL
8799 VARIABLES, INFORMATION_SCHEMA.GLOBAL_VARIABLES and @@sql_replica_skip_counter
8800 without taking all the mutexes needed to access
8801 active_mi->rli->slave_skip_counter properly.
8802 */
8803 uint sql_replica_skip_counter;
8804
8805 /**
8806 Executes a START SLAVE statement.
8807
8808 @param thd Pointer to THD object for the client thread
8809 executing the statement.
8810
8811 @param connection_param Connection parameters for starting threads
8812
8813 @param master_param Master parameters used for starting threads
8814
8815 @param thread_mask_input The thread mask that identifies which threads to
8816 start. If 0 is passed (start no thread) then this
8817 parameter is ignored and all stopped threads are
8818 started
8819
8820 @param mi Pointer to Master_info object for the slave's IO
8821 thread.
8822
8823 @param set_mts_settings If true, the channel uses the server MTS
8824 configured settings when starting the applier
8825 thread.
8826
8827 @retval false success
8828 @retval true error
8829 */
8830 11122 bool start_slave(THD *thd, LEX_SLAVE_CONNECTION *connection_param,
8831 LEX_MASTER_INFO *master_param, int thread_mask_input,
8832 Master_info *mi, bool set_mts_settings) {
8833 11122 bool is_error = false;
8834 int thread_mask;
8835
8836
1/2
✓ Branch 0 taken 11122 times.
✗ Branch 1 not taken.
11122 DBUG_TRACE;
8837
8838 /*
8839 START SLAVE command should ignore 'read-only' and 'super_read_only'
8840 options so that it can update 'mysql.slave_master_info' and
8841 'mysql.slave_relay_log_info' replication repository tables.
8842 */
8843 11122 thd->set_skip_readonly_check();
8844 11122 Security_context *sctx = thd->security_context();
8845
8/16
✓ Branch 0 taken 11122 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11122 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 11119 times.
✓ Branch 6 taken 11122 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11122 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 11121 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
11125 if (!sctx->check_access(SUPER_ACL) &&
8846
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 !sctx->has_global_grant(STRING_WITH_LEN("REPLICATION_SLAVE_ADMIN"))
8847
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 .first) {
8848
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
8849 "SUPER or REPLICATION_SLAVE_ADMIN");
8850 1 return true;
8851 }
8852
8853
1/2
✓ Branch 0 taken 11121 times.
✗ Branch 1 not taken.
11121 mi->channel_wrlock();
8854
8855
4/4
✓ Branch 0 taken 10997 times.
✓ Branch 1 taken 124 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 10994 times.
11121 if (connection_param->user || connection_param->password) {
8856
3/4
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✓ Branch 3 taken 36 times.
127 if (!thd->get_ssl()) {
8857
2/4
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✗ Branch 3 not taken.
91 push_warning(thd, Sql_condition::SL_NOTE, ER_INSECURE_PLAIN_TEXT,
8858 ER_THD(thd, ER_INSECURE_PLAIN_TEXT));
8859 }
8860 }
8861
8862
1/2
✓ Branch 0 taken 11121 times.
✗ Branch 1 not taken.
11121 lock_slave_threads(mi); // this allows us to cleanly read slave_running
8863 // Get a mask of _stopped_ threads
8864
1/2
✓ Branch 0 taken 11121 times.
✗ Branch 1 not taken.
11121 init_thread_mask(&thread_mask, mi, true /* inverse */);
8865 /*
8866 Below we will start all stopped threads. But if the user wants to
8867 start only one thread, do as if the other thread was running (as we
8868 don't want to touch the other thread), so set the bit to 0 for the
8869 other thread
8870 */
8871
2/2
✓ Branch 0 taken 5424 times.
✓ Branch 1 taken 5697 times.
11121 if (thread_mask_input) {
8872 5424 thread_mask &= thread_mask_input;
8873 }
8874
2/2
✓ Branch 0 taken 11086 times.
✓ Branch 1 taken 35 times.
11121 if (thread_mask) // some threads are stopped, start them
8875 {
8876
3/4
✓ Branch 0 taken 11080 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 11075 times.
11086 if (load_mi_and_rli_from_repositories(mi, false, thread_mask)) {
8877 5 is_error = true;
8878
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_MASTER_INFO, MYF(0));
8879
4/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 11062 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 10 times.
11075 } else if (*mi->host || !(thread_mask & SLAVE_IO)) {
8880 /*
8881 If we will start IO thread we need to take care of possible
8882 options provided through the START SLAVE if there is any.
8883 */
8884
2/2
✓ Branch 0 taken 7324 times.
✓ Branch 1 taken 3741 times.
11065 if (thread_mask & SLAVE_IO) {
8885
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 7200 times.
7324 if (connection_param->user) {
8886 124 mi->set_start_user_configured(true);
8887
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
124 mi->set_user(connection_param->user);
8888 }
8889
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 7206 times.
7324 if (connection_param->password) {
8890 118 mi->set_start_user_configured(true);
8891
1/2
✓ Branch 0 taken 118 times.
✗ Branch 1 not taken.
118 mi->set_password(connection_param->password);
8892 }
8893
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 7262 times.
7324 if (connection_param->plugin_auth)
8894
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 mi->set_plugin_auth(connection_param->plugin_auth);
8895
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 7282 times.
7324 if (connection_param->plugin_dir)
8896
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 mi->set_plugin_dir(connection_param->plugin_dir);
8897 }
8898
8899 /*
8900 If we will start SQL thread we will care about UNTIL options If
8901 not and they are specified we will ignore them and warn user
8902 about this fact.
8903 */
8904
2/2
✓ Branch 0 taken 10327 times.
✓ Branch 1 taken 738 times.
11065 if (thread_mask & SLAVE_SQL) {
8905 /*
8906 sql_replica_skip_counter only effects the applier thread which is
8907 first started. So after sql_replica_skip_counter is copied to
8908 rli->slave_skip_counter, it is reset to 0.
8909 */
8910
1/2
✓ Branch 0 taken 10327 times.
✗ Branch 1 not taken.
10327 mysql_mutex_lock(&LOCK_sql_replica_skip_counter);
8911
1/2
✓ Branch 0 taken 10327 times.
✗ Branch 1 not taken.
10327 if (mi->rli->m_assign_gtids_to_anonymous_transactions_info.get_type() !=
8912 Assign_gtids_to_anonymous_transactions_info::enum_type::
8913
4/4
✓ Branch 0 taken 10299 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 5559 times.
✓ Branch 3 taken 4768 times.
20626 AGAT_OFF ||
8914
3/4
✓ Branch 0 taken 10299 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5531 times.
✓ Branch 3 taken 4768 times.
10299 global_gtid_mode.get() != Gtid_mode::ON)
8915 5559 mi->rli->slave_skip_counter = sql_replica_skip_counter;
8916 10327 sql_replica_skip_counter = 0;
8917
1/2
✓ Branch 0 taken 10327 times.
✗ Branch 1 not taken.
10327 mysql_mutex_unlock(&LOCK_sql_replica_skip_counter);
8918 /*
8919 To cache the MTS system var values and used them in the following
8920 runtime. The system vars can change meanwhile but having no other
8921 effects.
8922 It also allows the per channel definition of this variables.
8923 */
8924
2/2
✓ Branch 0 taken 10325 times.
✓ Branch 1 taken 2 times.
10327 if (set_mts_settings) {
8925 10325 mi->rli->opt_replica_parallel_workers =
8926 opt_mts_replica_parallel_workers;
8927
5/6
✓ Branch 0 taken 10325 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3637 times.
✓ Branch 3 taken 6688 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 10320 times.
13962 if (mi->is_gtid_only_mode() &&
8928
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3632 times.
3637 opt_mts_replica_parallel_workers == 0) {
8929 5 mi->rli->opt_replica_parallel_workers = 1;
8930 }
8931
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 10276 times.
10325 if (mts_parallel_option == MTS_PARALLEL_TYPE_DB_NAME)
8932 49 mi->rli->channel_mts_submode = MTS_PARALLEL_TYPE_DB_NAME;
8933 else
8934 10276 mi->rli->channel_mts_submode = MTS_PARALLEL_TYPE_LOGICAL_CLOCK;
8935
8936 #ifndef NDEBUG
8937
2/4
✓ Branch 0 taken 10325 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10325 times.
✗ Branch 3 not taken.
10325 if (!DBUG_EVALUATE_IF("check_replica_debug_group", 1, 0))
8938 #endif
8939 10325 mi->rli->checkpoint_group = opt_mta_checkpoint_group;
8940 }
8941
8942
1/2
✓ Branch 0 taken 10327 times.
✗ Branch 1 not taken.
10327 int slave_errno = mi->rli->init_until_option(thd, master_param);
8943
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 10321 times.
10327 if (slave_errno) {
8944
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(slave_errno, MYF(0));
8945 6 is_error = true;
8946 }
8947
8948
3/4
✓ Branch 0 taken 10321 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 10321 times.
✗ Branch 3 not taken.
10327 if (!is_error) is_error = check_slave_sql_config_conflict(mi->rli);
8949
2/4
✓ Branch 0 taken 738 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 738 times.
✗ Branch 3 not taken.
738 } else if (master_param->pos || master_param->relay_log_pos ||
8950
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 736 times.
738 master_param->gtid)
8951
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 push_warning(thd, Sql_condition::SL_NOTE, ER_UNTIL_COND_IGNORED,
8952 ER_THD(thd, ER_UNTIL_COND_IGNORED));
8953
8954
2/2
✓ Branch 0 taken 11053 times.
✓ Branch 1 taken 12 times.
11065 if (!is_error)
8955 is_error =
8956
1/2
✓ Branch 0 taken 11053 times.
✗ Branch 1 not taken.
11053 start_slave_threads(false /*need_lock_slave=false*/,
8957 true /*wait_for_start=true*/, mi, thread_mask);
8958 11065 } else {
8959 10 is_error = true;
8960
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 my_error(ER_BAD_SLAVE, MYF(0));
8961 }
8962 } else {
8963 /* no error if all threads are already started, only a warning */
8964
2/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
35 push_warning_printf(
8965 thd, Sql_condition::SL_NOTE, ER_SLAVE_CHANNEL_WAS_RUNNING,
8966 ER_THD(thd, ER_SLAVE_CHANNEL_WAS_RUNNING), mi->get_channel());
8967 }
8968
8969 /*
8970 Clean up start information if there was an attempt to start
8971 the IO thread to avoid any security issue.
8972 */
8973
5/6
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 11064 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
11115 if (is_error && (thread_mask & SLAVE_IO) == SLAVE_IO) mi->reset_start_info();
8974
8975
1/2
✓ Branch 0 taken 11115 times.
✗ Branch 1 not taken.
11115 unlock_slave_threads(mi);
8976
8977
1/2
✓ Branch 0 taken 11115 times.
✗ Branch 1 not taken.
11115 mi->channel_unlock();
8978
8979 11115 return is_error;
8980 11116 }
8981
8982 /**
8983 Execute a STOP SLAVE statement.
8984
8985 @param thd Pointer to THD object for the client thread executing
8986 the statement.
8987
8988 @param mi Pointer to Master_info object for the slave's IO
8989 thread.
8990
8991 @param net_report If true, saves the exit status into Diagnostics_area.
8992
8993 @param for_one_channel If the method is being invoked only for one channel
8994
8995 @param push_temp_tables_warning If it should push a "have temp tables
8996 warning" once having open temp tables. This
8997 avoids multiple warnings when there is more
8998 than one channel with open temp tables.
8999 This parameter can be removed when the
9000 warning is issued with per-channel
9001 information.
9002
9003 @retval 0 success
9004 @retval 1 error
9005 */
9006 6338 int stop_slave(THD *thd, Master_info *mi, bool net_report, bool for_one_channel,
9007 bool *push_temp_tables_warning) {
9008
1/2
✓ Branch 0 taken 6338 times.
✗ Branch 1 not taken.
6338 DBUG_TRACE;
9009
9010 int slave_errno;
9011
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6338 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6338 if (!thd) thd = current_thd;
9012
9013 /*
9014 STOP SLAVE command should ignore 'read-only' and 'super_read_only'
9015 options so that it can update 'mysql.slave_master_info' and
9016 'mysql.slave_relay_log_info' replication repository tables.
9017 */
9018 6338 thd->set_skip_readonly_check();
9019
9020 6338 Security_context *sctx = thd->security_context();
9021
8/16
✓ Branch 0 taken 6338 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6338 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 6337 times.
✓ Branch 6 taken 6338 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6338 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 6337 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
6339 if (!sctx->check_access(SUPER_ACL) &&
9022
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 !sctx->has_global_grant(STRING_WITH_LEN("REPLICATION_SLAVE_ADMIN"))
9023
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 .first) {
9024
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
9025 "SUPER or REPLICATION_SLAVE_ADMIN");
9026 1 return 1;
9027 }
9028
9029
1/2
✓ Branch 0 taken 6337 times.
✗ Branch 1 not taken.
6337 mi->channel_wrlock();
9030
9031
1/2
✓ Branch 0 taken 6337 times.
✗ Branch 1 not taken.
6337 THD_STAGE_INFO(thd, stage_killing_replica);
9032 int thread_mask;
9033
1/2
✓ Branch 0 taken 6337 times.
✗ Branch 1 not taken.
6337 lock_slave_threads(mi);
9034
9035
2/6
✓ Branch 0 taken 6337 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6337 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
6337 DBUG_EXECUTE_IF("simulate_hold_run_locks_on_stop_replica",
9036 my_sleep(10000000););
9037
9038 // Get a mask of _running_ threads
9039
1/2
✓ Branch 0 taken 6337 times.
✗ Branch 1 not taken.
6337 init_thread_mask(&thread_mask, mi, false /* not inverse*/);
9040
9041 /*
9042 Below we will stop all running threads.
9043 But if the user wants to stop only one thread, do as if the other thread
9044 was stopped (as we don't want to touch the other thread), so set the
9045 bit to 0 for the other thread
9046 */
9047
2/2
✓ Branch 0 taken 1315 times.
✓ Branch 1 taken 5022 times.
6337 if (thd->lex->slave_thd_opt) {
9048 1315 thread_mask &= thd->lex->slave_thd_opt;
9049
9050 /*
9051 If we are stopping IO thread, we also need to consider
9052 IO Monitor thread.
9053 */
9054
6/6
✓ Branch 0 taken 572 times.
✓ Branch 1 taken 743 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 566 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 1309 times.
1315 if ((thread_mask & SLAVE_IO) && mi->is_source_connection_auto_failover()) {
9055 6 thread_mask |= SLAVE_MONITOR;
9056 }
9057 }
9058
9059
2/2
✓ Branch 0 taken 6072 times.
✓ Branch 1 taken 265 times.
6337 if (thread_mask) {
9060 slave_errno =
9061
1/2
✓ Branch 0 taken 6072 times.
✗ Branch 1 not taken.
6072 terminate_slave_threads(mi, thread_mask, rpl_stop_replica_timeout,
9062 false /*need_lock_term=false*/);
9063 } else {
9064 // no error if both threads are already stopped, only a warning
9065 265 slave_errno = 0;
9066
2/4
✓ Branch 0 taken 265 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 265 times.
✗ Branch 3 not taken.
265 push_warning_printf(
9067 thd, Sql_condition::SL_NOTE, ER_SLAVE_CHANNEL_WAS_NOT_RUNNING,
9068 ER_THD(thd, ER_SLAVE_CHANNEL_WAS_NOT_RUNNING), mi->get_channel());
9069 }
9070
9071 /*
9072 If the slave has open temp tables and there is a following CHANGE MASTER
9073 there is a possibility that the temporary tables are left open forever.
9074 Though we dont restrict failover here, we do warn users. In future, we
9075 should have a command to delete open temp tables the slave has replicated.
9076 See WL#7441 regarding this command.
9077 */
9078
9079
6/6
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 6316 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 6317 times.
6337 if (mi->rli->atomic_channel_open_temp_tables && *push_temp_tables_warning) {
9080
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 push_warning(thd, Sql_condition::SL_WARNING,
9081 ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO,
9082 ER_THD(thd, ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO));
9083 20 *push_temp_tables_warning = false;
9084 }
9085
9086
1/2
✓ Branch 0 taken 6337 times.
✗ Branch 1 not taken.
6337 unlock_slave_threads(mi);
9087
9088
1/2
✓ Branch 0 taken 6337 times.
✗ Branch 1 not taken.
6337 mi->channel_unlock();
9089
9090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6337 times.
6337 if (slave_errno) {
9091 if ((slave_errno == ER_STOP_SLAVE_SQL_THREAD_TIMEOUT) ||
9092 (slave_errno == ER_STOP_REPLICA_MONITOR_IO_THREAD_TIMEOUT) ||
9093 (slave_errno == ER_STOP_SLAVE_IO_THREAD_TIMEOUT)) {
9094 push_warning(thd, Sql_condition::SL_NOTE, slave_errno,
9095 ER_THD_NONCONST(thd, slave_errno));
9096
9097 /*
9098 If new slave_errno is added in the if() condition above then make sure
9099 that there are no % in the error message or change the logging API
9100 to use verbatim() to avoid % substitutions.
9101 */
9102 longlong log_errno = (slave_errno == ER_STOP_SLAVE_SQL_THREAD_TIMEOUT)
9103 ? ER_RPL_SLAVE_SQL_THREAD_STOP_CMD_EXEC_TIMEOUT
9104 : ER_RPL_SLAVE_IO_THREAD_STOP_CMD_EXEC_TIMEOUT;
9105 LogErr(WARNING_LEVEL, log_errno);
9106 }
9107 if (net_report) my_error(slave_errno, MYF(0));
9108 return 1;
9109
3/4
✓ Branch 0 taken 6337 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 445 times.
✓ Branch 3 taken 5892 times.
6337 } else if (net_report && for_one_channel)
9110
1/2
✓ Branch 0 taken 445 times.
✗ Branch 1 not taken.
445 my_ok(thd);
9111
9112 6337 return 0;
9113 6338 }
9114
9115 /**
9116 Execute a RESET SLAVE (for all channels), used in Multisource replication.
9117 If resetting of a particular channel fails, it exits out.
9118
9119 @param[in] thd THD object of the client.
9120
9121 @retval 0 success
9122 @retval 1 error
9123 */
9124
9125 1445 int reset_slave(THD *thd) {
9126
1/2
✓ Branch 0 taken 1445 times.
✗ Branch 1 not taken.
1445 DBUG_TRACE;
9127
9128
1/2
✓ Branch 0 taken 1445 times.
✗ Branch 1 not taken.
1445 channel_map.assert_some_wrlock();
9129
9130 1445 Master_info *mi = nullptr;
9131 1445 int result = 0;
9132 1445 mi_map::iterator it, gr_channel_map_it;
9133
2/2
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 1118 times.
1445 if (thd->lex->reset_slave_info.all) {
9134 /* First do reset_slave for default channel */
9135
1/2
✓ Branch 0 taken 327 times.
✗ Branch 1 not taken.
327 mi = channel_map.get_default_channel_mi();
9136
6/8
✓ Branch 0 taken 327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 327 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 325 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 325 times.
327 if (mi && reset_slave(thd, mi, thd->lex->reset_slave_info.all)) return 1;
9137 /* Do while iteration for rest of the channels */
9138
1/2
✓ Branch 0 taken 325 times.
✗ Branch 1 not taken.
325 it = channel_map.begin();
9139
3/4
✓ Branch 0 taken 720 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 395 times.
✓ Branch 3 taken 325 times.
720 while (it != channel_map.end()) {
9140
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 35 times.
395 if (!it->first.compare(channel_map.get_default_channel())) {
9141 360 it++;
9142 360 continue;
9143 }
9144 35 mi = it->second;
9145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 assert(mi);
9146
2/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35 times.
35 if ((result = reset_slave(thd, mi, thd->lex->reset_slave_info.all)))
9147 break;
9148
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 it = channel_map.begin();
9149 }
9150 /* RESET group replication specific channels */
9151
1/2
✓ Branch 0 taken 325 times.
✗ Branch 1 not taken.
325 gr_channel_map_it = channel_map.begin(GROUP_REPLICATION_CHANNEL);
9152
3/4
✓ Branch 0 taken 330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 324 times.
330 while (gr_channel_map_it != channel_map.end(GROUP_REPLICATION_CHANNEL)) {
9153 6 mi = gr_channel_map_it->second;
9154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 assert(mi);
9155 /*
9156 We cannot RESET a group replication channel while the group
9157 replication is running.
9158 */
9159
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5 times.
6 if (is_group_replication_running()) {
9160
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
9161 "RESET SLAVE ALL FOR CHANNEL", mi->get_channel());
9162 1 return 1;
9163 }
9164
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if ((result = reset_slave(thd, mi, thd->lex->reset_slave_info.all)))
9165 break;
9166
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 gr_channel_map_it = channel_map.begin(GROUP_REPLICATION_CHANNEL);
9167 }
9168 } else {
9169
1/2
✓ Branch 0 taken 1118 times.
✗ Branch 1 not taken.
1118 it = channel_map.begin();
9170
3/4
✓ Branch 0 taken 2236 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1121 times.
✓ Branch 3 taken 1115 times.
2236 while (it != channel_map.end()) {
9171 1121 mi = it->second;
9172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1121 times.
1121 assert(mi);
9173
3/4
✓ Branch 0 taken 1121 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1118 times.
1121 if ((result = reset_slave(thd, mi, thd->lex->reset_slave_info.all)))
9174 3 break;
9175 1118 it++;
9176 }
9177 /*
9178 RESET group replication specific channels.
9179
9180 We cannot RESET a group replication channel while the group
9181 replication is running.
9182 */
9183
1/2
✓ Branch 0 taken 1118 times.
✗ Branch 1 not taken.
1118 gr_channel_map_it = channel_map.begin(GROUP_REPLICATION_CHANNEL);
9184
3/4
✓ Branch 0 taken 1123 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1118 times.
1123 while (gr_channel_map_it != channel_map.end(GROUP_REPLICATION_CHANNEL)) {
9185 5 mi = gr_channel_map_it->second;
9186
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(mi);
9187
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (is_group_replication_running()) {
9188 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
9189 "RESET SLAVE FOR CHANNEL", mi->get_channel());
9190 return 1;
9191 }
9192
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if ((result = reset_slave(thd, mi, thd->lex->reset_slave_info.all)))
9193 break;
9194 5 gr_channel_map_it++;
9195 }
9196 }
9197 1442 return result;
9198 1445 }
9199
9200 /**
9201 Execute a RESET REPLICA statement.
9202 Locks slave threads and unlocks the slave threads after executing
9203 reset slave.
9204 The method also takes the mi->channel_wrlock; if this {mi} object
9205 is deleted (when the parameter reset_all is true) its destructor unlocks
9206 the lock. In case of error, the method shall always unlock the
9207 mi channel lock.
9208
9209 @param thd Pointer to THD object of the client thread executing the
9210 statement.
9211
9212 @param mi Pointer to Master_info object for the slave.
9213
9214 @param reset_all Do a full reset or only clean master info structures
9215
9216 @retval 0 success
9217 @retval !=0 error
9218 */
9219 13001 int reset_slave(THD *thd, Master_info *mi, bool reset_all) {
9220 13001 int thread_mask = 0, error = 0;
9221 13001 const char *errmsg = "Unknown error occurred while reseting slave";
9222
1/2
✓ Branch 0 taken 13001 times.
✗ Branch 1 not taken.
13001 DBUG_TRACE;
9223
9224 bool is_default_channel =
9225 13001 strcmp(mi->get_channel(), channel_map.get_default_channel()) == 0;
9226
9227 /*
9228 RESET SLAVE command should ignore 'read-only' and 'super_read_only'
9229 options so that it can update 'mysql.slave_master_info' and
9230 'mysql.slave_relay_log_info' replication repository tables.
9231 */
9232 13001 thd->set_skip_readonly_check();
9233
1/2
✓ Branch 0 taken 13001 times.
✗ Branch 1 not taken.
13001 mi->channel_wrlock();
9234
9235
1/2
✓ Branch 0 taken 13001 times.
✗ Branch 1 not taken.
13001 lock_slave_threads(mi);
9236
1/2
✓ Branch 0 taken 13001 times.
✗ Branch 1 not taken.
13001 init_thread_mask(&thread_mask, mi, false /* not inverse */,
9237 true /* ignore_monitor_thread */);
9238
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 12986 times.
13001 if (thread_mask) // We refuse if any slave thread is running
9239 {
9240
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 my_error(ER_SLAVE_CHANNEL_MUST_STOP, MYF(0), mi->get_channel());
9241 15 error = ER_SLAVE_CHANNEL_MUST_STOP;
9242
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 unlock_slave_threads(mi);
9243
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 mi->channel_unlock();
9244 15 goto err;
9245 }
9246
9247
1/2
✓ Branch 0 taken 12986 times.
✗ Branch 1 not taken.
12986 ha_reset_slave(thd);
9248
9249 // delete relay logs, clear relay log coordinates
9250
3/4
✓ Branch 0 taken 12986 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 12983 times.
12986 if ((error = mi->rli->purge_relay_logs(thd, &errmsg,
9251
4/4
✓ Branch 0 taken 9201 times.
✓ Branch 1 taken 3785 times.
✓ Branch 2 taken 2846 times.
✓ Branch 3 taken 6355 times.
12986 reset_all && !is_default_channel))) {
9252
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_RELAY_LOG_FAIL, MYF(0), errmsg);
9253 3 error = ER_RELAY_LOG_FAIL;
9254
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 unlock_slave_threads(mi);
9255
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mi->channel_unlock();
9256 3 goto err;
9257 }
9258
9259
2/4
✓ Branch 0 taken 12983 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12983 times.
12983 assert(!mi->rli || !mi->rli->slave_running); // none writes in rli table
9260
7/8
✓ Branch 0 taken 9201 times.
✓ Branch 1 taken 3782 times.
✓ Branch 2 taken 9201 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9200 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 12982 times.
25965 if ((reset_all && remove_info(mi)) || // Removes all repository information.
9261
4/6
✓ Branch 0 taken 3782 times.
✓ Branch 1 taken 9200 times.
✓ Branch 2 taken 3782 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3782 times.
12982 (!reset_all && reset_info(mi))) { // Resets log names, positions, etc,
9262 // but keeps configuration information
9263 // needed for a re-connection.
9264 1 error = ER_UNKNOWN_ERROR;
9265
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_UNKNOWN_ERROR, MYF(0));
9266
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 unlock_slave_threads(mi);
9267
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mi->channel_unlock();
9268 1 goto err;
9269 }
9270
1/2
✓ Branch 0 taken 12982 times.
✗ Branch 1 not taken.
12982 unlock_slave_threads(mi);
9271
9272
4/6
✓ Branch 0 taken 12982 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6954 times.
✓ Branch 3 taken 6028 times.
✓ Branch 4 taken 6954 times.
✗ Branch 5 not taken.
12982 (void)RUN_HOOK(binlog_relay_io, after_reset_slave, (thd, mi));
9273
9274 /*
9275 RESET SLAVE ALL deletes the channels(except default channel), so their mi
9276 and rli objects are removed. For default channel, its mi and rli are
9277 deleted and recreated to keep in clear status.
9278 */
9279
2/2
✓ Branch 0 taken 9200 times.
✓ Branch 1 taken 3782 times.
12982 if (reset_all) {
9280 bool is_default =
9281 9200 !strcmp(mi->get_channel(), channel_map.get_default_channel());
9282
9283
2/4
✓ Branch 0 taken 9200 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9200 times.
✗ Branch 3 not taken.
18400 rpl_acf_configuration_handler->delete_channel_status(
9284 9200 mi->get_channel(),
9285 Rpl_acf_status_configuration::SOURCE_CONNECTION_AUTO_FAILOVER);
9286
9287 // delete_mi will call mi->channel_unlock in case it succeeds
9288
2/4
✓ Branch 0 taken 9200 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9200 times.
9200 if (channel_map.delete_mi(mi->get_channel())) {
9289 mi->channel_unlock();
9290 error = ER_UNKNOWN_ERROR;
9291 my_error(ER_UNKNOWN_ERROR, MYF(0));
9292 goto err;
9293 }
9294
9295
2/2
✓ Branch 0 taken 6355 times.
✓ Branch 1 taken 2845 times.
9200 if (is_default) {
9296
3/4
✓ Branch 0 taken 6355 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6353 times.
6355 if (!Rpl_info_factory::create_mi_and_rli_objects(
9297 opt_mi_repository_id, opt_rli_repository_id,
9298 channel_map.get_default_channel(), true, &channel_map)) {
9299 2 error = ER_MASTER_INFO;
9300
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 my_message(ER_MASTER_INFO, ER_THD(thd, ER_MASTER_INFO), MYF(0));
9301 }
9302 }
9303 } else {
9304
1/2
✓ Branch 0 taken 3782 times.
✗ Branch 1 not taken.
3782 mi->channel_unlock();
9305 }
9306
9307 13001 err:
9308 13001 return error;
9309 13001 }
9310
9311 /**
9312 Entry function for RESET SLAVE command. Function either resets
9313 the slave for all channels or for a single channel.
9314 When RESET SLAVE ALL is given, the slave_info_objects (mi, rli & workers)
9315 are destroyed.
9316
9317 @param[in] thd the client thread with the command.
9318
9319 @retval false OK
9320 @retval true not OK
9321 */
9322 13338 bool reset_slave_cmd(THD *thd) {
9323
1/2
✓ Branch 0 taken 13338 times.
✗ Branch 1 not taken.
13338 DBUG_TRACE;
9324
9325 Master_info *mi;
9326 13338 LEX *lex = thd->lex;
9327 13338 bool res = true; // default, an error
9328
9329
1/2
✓ Branch 0 taken 13338 times.
✗ Branch 1 not taken.
13338 channel_map.wrlock();
9330
9331
3/4
✓ Branch 0 taken 13338 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 13337 times.
13338 if (!is_slave_configured()) {
9332
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SLAVE_CONFIGURATION, MYF(0));
9333
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 channel_map.unlock();
9334 1 return res = true;
9335 }
9336
9337
2/2
✓ Branch 0 taken 1445 times.
✓ Branch 1 taken 11892 times.
13337 if (!lex->mi.for_channel)
9338
1/2
✓ Branch 0 taken 1445 times.
✗ Branch 1 not taken.
1445 res = reset_slave(thd);
9339 else {
9340
1/2
✓ Branch 0 taken 11892 times.
✗ Branch 1 not taken.
11892 mi = channel_map.get_mi(lex->mi.channel);
9341 /*
9342 If the channel being used is a group replication channel and
9343 group_replication is still running we need to disable RESET SLAVE [ALL]
9344 command.
9345 */
9346 20777 if (mi &&
9347
3/4
✓ Branch 0 taken 8885 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 592 times.
✓ Branch 3 taken 8293 times.
8885 channel_map.is_group_replication_channel_name(mi->get_channel(),
9348
4/4
✓ Branch 0 taken 8885 times.
✓ Branch 1 taken 3007 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 11887 times.
20777 true) &&
9349
3/4
✓ Branch 0 taken 592 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 587 times.
592 is_group_replication_running()) {
9350
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
9351 "RESET SLAVE [ALL] FOR CHANNEL", mi->get_channel());
9352
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 channel_map.unlock();
9353 5 return true;
9354 }
9355
9356
2/2
✓ Branch 0 taken 8880 times.
✓ Branch 1 taken 3007 times.
11887 if (mi)
9357
1/2
✓ Branch 0 taken 8880 times.
✗ Branch 1 not taken.
8880 res = reset_slave(thd, mi, thd->lex->reset_slave_info.all);
9358
1/2
✓ Branch 0 taken 3007 times.
✗ Branch 1 not taken.
3007 else if (strcmp(channel_map.get_default_channel(), lex->mi.channel))
9359
1/2
✓ Branch 0 taken 3007 times.
✗ Branch 1 not taken.
3007 my_error(ER_SLAVE_CHANNEL_DOES_NOT_EXIST, MYF(0), lex->mi.channel);
9360 }
9361
9362
1/2
✓ Branch 0 taken 13332 times.
✗ Branch 1 not taken.
13332 channel_map.unlock();
9363
9364 13332 return res;
9365 13338 }
9366
9367 /**
9368 This function checks if the given CHANGE MASTER/REPLICATION SOURCE command
9369 has any receive option being set or changed.
9370
9371 - used in change_master().
9372
9373 @param lex_mi structure that holds all options given on the
9374 change replication source command.
9375
9376 @retval false No change replication source receive options were found.
9377 @retval true At least one receive option was found.
9378 */
9379 12785 static bool have_change_replication_source_receive_option(
9380 const LEX_MASTER_INFO *lex_mi) {
9381 12785 bool have_receive_option = false;
9382
9383
1/2
✓ Branch 0 taken 12785 times.
✗ Branch 1 not taken.
12785 DBUG_TRACE;
9384
9385 /* Check if *at least one* receive option is given the command*/
9386
6/6
✓ Branch 0 taken 4121 times.
✓ Branch 1 taken 8664 times.
✓ Branch 2 taken 2102 times.
✓ Branch 3 taken 2019 times.
✓ Branch 4 taken 2091 times.
✓ Branch 5 taken 11 times.
12785 if (lex_mi->host || lex_mi->user || lex_mi->password ||
9387
6/6
✓ Branch 0 taken 2058 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 2037 times.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 2023 times.
✓ Branch 5 taken 14 times.
2091 lex_mi->log_file_name || lex_mi->pos || lex_mi->bind_addr ||
9388
5/6
✓ Branch 0 taken 2023 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1989 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 1912 times.
✓ Branch 5 taken 77 times.
2023 lex_mi->network_namespace || lex_mi->port || lex_mi->connect_retry ||
9389
3/4
✓ Branch 0 taken 1912 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1886 times.
✓ Branch 3 taken 26 times.
1912 lex_mi->server_id || lex_mi->ssl != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9390
2/2
✓ Branch 0 taken 1882 times.
✓ Branch 1 taken 4 times.
1886 lex_mi->ssl_verify_server_cert != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9391
2/2
✓ Branch 0 taken 1840 times.
✓ Branch 1 taken 42 times.
1882 lex_mi->heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9392
2/2
✓ Branch 0 taken 1803 times.
✓ Branch 1 taken 37 times.
1840 lex_mi->retry_count_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9393
6/6
✓ Branch 0 taken 1798 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1794 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1790 times.
✓ Branch 5 taken 4 times.
1803 lex_mi->ssl_key || lex_mi->ssl_cert || lex_mi->ssl_ca ||
9394
4/4
✓ Branch 0 taken 1788 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1786 times.
✓ Branch 3 taken 2 times.
1790 lex_mi->ssl_capath || lex_mi->tls_version ||
9395
2/2
✓ Branch 0 taken 1775 times.
✓ Branch 1 taken 11 times.
1786 lex_mi->tls_ciphersuites != LEX_MASTER_INFO::UNSPECIFIED ||
9396
6/6
✓ Branch 0 taken 1773 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1770 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1768 times.
✓ Branch 5 taken 2 times.
1775 lex_mi->ssl_cipher || lex_mi->ssl_crl || lex_mi->ssl_crlpath ||
9397
2/2
✓ Branch 0 taken 1739 times.
✓ Branch 1 taken 29 times.
1768 lex_mi->repl_ignore_server_ids_opt == LEX_MASTER_INFO::LEX_MI_ENABLE ||
9398
2/2
✓ Branch 0 taken 1737 times.
✓ Branch 1 taken 2 times.
1739 lex_mi->public_key_path ||
9399
2/2
✓ Branch 0 taken 1735 times.
✓ Branch 1 taken 2 times.
1737 lex_mi->get_public_key != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9400
4/4
✓ Branch 0 taken 1656 times.
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 1573 times.
✓ Branch 3 taken 83 times.
1735 lex_mi->zstd_compression_level || lex_mi->compression_algorithm ||
9401
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 1486 times.
1573 lex_mi->require_row_format != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9402 11299 have_receive_option = true;
9403
9404 12785 return have_receive_option;
9405 12785 }
9406
9407 /**
9408 This function checks if the given CHANGE MASTER/REPLICATION SOURCE command
9409 has any execute option being set or changed.
9410
9411 - used in change_master().
9412
9413 @param lex_mi structure that holds all options given on the
9414 change replication source command.
9415
9416 @param[out] need_relay_log_purge
9417 - If relay_log_file/relay_log_pos options are used,
9418 we won't delete relaylogs. We set this boolean flag to false.
9419 - If relay_log_file/relay_log_pos options are NOT used,
9420 we return the boolean flag UNCHANGED.
9421 - Used in change_receive_options() and change_master().
9422
9423 @retval false No change replication source execute option.
9424 @retval true At least one execute option was there.
9425 */
9426 12785 static bool have_change_replication_source_execute_option(
9427 const LEX_MASTER_INFO *lex_mi, bool *need_relay_log_purge) {
9428 12785 bool have_execute_option = false;
9429
9430
1/2
✓ Branch 0 taken 12785 times.
✗ Branch 1 not taken.
12785 DBUG_TRACE;
9431
9432 /* Check if *at least one* execute option is given on change master command*/
9433
4/4
✓ Branch 0 taken 12721 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 12715 times.
✓ Branch 3 taken 6 times.
12785 if (lex_mi->relay_log_name || lex_mi->relay_log_pos ||
9434
4/4
✓ Branch 0 taken 12616 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 12574 times.
✓ Branch 3 taken 42 times.
12715 lex_mi->sql_delay != -1 || lex_mi->privilege_checks_username != nullptr ||
9435
2/2
✓ Branch 0 taken 9609 times.
✓ Branch 1 taken 2965 times.
12574 lex_mi->privilege_checks_none ||
9436
2/2
✓ Branch 0 taken 9537 times.
✓ Branch 1 taken 72 times.
9609 lex_mi->require_row_format != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9437
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 9516 times.
9537 lex_mi->require_table_primary_key_check !=
9438 LEX_MASTER_INFO::LEX_MI_PK_CHECK_UNCHANGED)
9439 3269 have_execute_option = true;
9440
9441
4/4
✓ Branch 0 taken 12721 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 12715 times.
12785 if (lex_mi->relay_log_name || lex_mi->relay_log_pos)
9442 70 *need_relay_log_purge = false;
9443
9444 12785 return have_execute_option;
9445 12785 }
9446
9447 /**
9448 This function checks if the given CHANGE REPLICATION SOURCE command has
9449 any option that affect both the receiver and the applier.
9450
9451 - used in change_master().
9452
9453 @param lex_mi structure that holds all options given on the
9454 change replication source command.
9455
9456 @retval false no option that affects both applier and receiver was found
9457 @retval true At least one option affects both the applier and receiver.
9458 */
9459 12785 static bool have_change_replication_source_applier_and_receive_option(
9460 const LEX_MASTER_INFO *lex_mi) {
9461 12785 bool have_applier_receive_option = false;
9462
9463
1/2
✓ Branch 0 taken 12785 times.
✗ Branch 1 not taken.
12785 DBUG_TRACE;
9464
9465 /* Check if *at least one* receive option is given to change rep source*/
9466
2/2
✓ Branch 0 taken 12748 times.
✓ Branch 1 taken 37 times.
12785 if (lex_mi->assign_gtids_to_anonymous_transactions_type !=
9467 12748 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UNCHANGED ||
9468
2/2
✓ Branch 0 taken 6864 times.
✓ Branch 1 taken 5884 times.
12748 lex_mi->auto_position != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9469
2/2
✓ Branch 0 taken 6829 times.
✓ Branch 1 taken 35 times.
6864 lex_mi->m_source_connection_auto_failover !=
9470 6829 LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
9471
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 6798 times.
6829 lex_mi->m_gtid_only != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9472 5987 have_applier_receive_option = true;
9473
9474 12785 return have_applier_receive_option;
9475 12785 }
9476
9477 /**
9478 This function checks all possible cases in which compression algorithm,
9479 compression level can be configured for a channel.
9480
9481 - used in change_receive_options
9482
9483 @param lex_mi pointer to structure holding all options specified
9484 as part of change master to statement
9485 @param mi pointer to structure holding all options specified
9486 as part of change master to statement after performing
9487 necessary checks
9488
9489 @retval false in case of success
9490 @retval true in case of failures
9491 */
9492 11241 static bool change_master_set_compression(THD *, const LEX_MASTER_INFO *lex_mi,
9493 Master_info *mi) {
9494
1/2
✓ Branch 0 taken 11241 times.
✗ Branch 1 not taken.
11241 DBUG_TRACE;
9495
9496
2/2
✓ Branch 0 taken 1477 times.
✓ Branch 1 taken 9764 times.
11241 if (lex_mi->compression_algorithm) {
9497
4/6
✓ Branch 0 taken 1477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1477 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 1450 times.
2954 if (validate_compression_attributes(lex_mi->compression_algorithm,
9498
1/2
✓ Branch 0 taken 1477 times.
✗ Branch 1 not taken.
1477 lex_mi->channel, false))
9499 27 return true;
9500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1450 times.
1450 assert(sizeof(mi->compression_algorithm) >
9501 strlen(lex_mi->compression_algorithm));
9502 1450 strcpy(mi->compression_algorithm, lex_mi->compression_algorithm);
9503 }
9504 /* level specified */
9505
2/2
✓ Branch 0 taken 1437 times.
✓ Branch 1 taken 9777 times.
11214 if (lex_mi->zstd_compression_level) {
9506 /* vaildate compression level */
9507
3/4
✓ Branch 0 taken 1437 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 1428 times.
1437 if (!is_zstd_compression_level_valid(lex_mi->zstd_compression_level)) {
9508 9 my_error(ER_CHANGE_MASTER_WRONG_COMPRESSION_LEVEL_CLIENT, MYF(0),
9509
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 lex_mi->zstd_compression_level, lex_mi->channel);
9510 9 return true;
9511 }
9512 1428 mi->zstd_compression_level = lex_mi->zstd_compression_level;
9513 }
9514 11205 return false;
9515 11241 }
9516
9517 /**
9518 This function is called if the change master command had at least one
9519 receive option. This function then sets or alters the receive option(s)
9520 given in the command. The execute options are handled in the function
9521 change_execute_options()
9522
9523 - used in change_master().
9524 - Receiver threads should be stopped when this function is called.
9525
9526 @param thd Pointer to THD object for the client thread executing the
9527 statement.
9528
9529 @param lex_mi structure that holds all change master options given on the
9530 change master command.
9531 Coming from the an executing statement or set directly this
9532 shall contain connection settings like hostname, user, password
9533 and other settings like the number of connection retries.
9534
9535 @param mi Pointer to Master_info object belonging to the replica channel
9536 to be configured
9537
9538 @retval 0 no error i.e., success.
9539 @retval !=0 error.
9540 */
9541 11242 static int change_receive_options(THD *thd, LEX_MASTER_INFO *lex_mi,
9542 Master_info *mi) {
9543 11242 int ret = 0; /* return value. Set if there is an error. */
9544
9545
1/2
✓ Branch 0 taken 11242 times.
✗ Branch 1 not taken.
11242 DBUG_TRACE;
9546
9547 /*
9548 If the user specified host or port without binlog or position,
9549 reset binlog's name to FIRST and position to 4.
9550 */
9551
9552
4/4
✓ Branch 0 taken 8650 times.
✓ Branch 1 taken 2592 times.
✓ Branch 2 taken 917 times.
✓ Branch 3 taken 7733 times.
11242 if ((lex_mi->host && strcmp(lex_mi->host, mi->host)) ||
9553
4/4
✓ Branch 0 taken 250 times.
✓ Branch 1 taken 3259 times.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 170 times.
3509 (lex_mi->port && lex_mi->port != mi->port)) {
9554 /*
9555 This is necessary because the primary key, i.e. host or port, has
9556 changed.
9557
9558 The repository does not support direct changes on the primary key,
9559 so the row is dropped and re-inserted with a new primary key. If we
9560 don't do that, the master info repository we will end up with several
9561 rows.
9562 */
9563
2/4
✓ Branch 0 taken 7813 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7813 times.
7813 if (mi->clean_info()) {
9564 ret = 1;
9565 goto err;
9566 }
9567 7813 mi->master_uuid[0] = 0;
9568 7813 mi->master_id = 0;
9569 }
9570
9571
6/6
✓ Branch 0 taken 2592 times.
✓ Branch 1 taken 8650 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 2559 times.
✓ Branch 4 taken 8649 times.
✓ Branch 5 taken 34 times.
11242 if ((lex_mi->host || lex_mi->port) && !lex_mi->log_file_name &&
9572
2/2
✓ Branch 0 taken 8642 times.
✓ Branch 1 taken 7 times.
8649 !lex_mi->pos) {
9573 8642 char *var_master_log_name = nullptr;
9574 8642 var_master_log_name = const_cast<char *>(mi->get_master_log_name());
9575 8642 var_master_log_name[0] = '\0';
9576 8642 mi->set_master_log_pos(BIN_LOG_HEADER_SIZE);
9577 }
9578
9579
3/4
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 11180 times.
✓ Branch 2 taken 62 times.
✗ Branch 3 not taken.
11242 if (lex_mi->log_file_name) mi->set_master_log_name(lex_mi->log_file_name);
9580
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 11173 times.
11242 if (lex_mi->pos) {
9581 69 mi->set_master_log_pos(lex_mi->pos);
9582 }
9583
9584
4/4
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 11180 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 43 times.
11242 if (lex_mi->log_file_name && !lex_mi->pos)
9585
2/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
19 push_warning(thd, Sql_condition::SL_WARNING,
9586 ER_WARN_ONLY_MASTER_LOG_FILE_NO_POS,
9587 ER_THD(thd, ER_WARN_ONLY_MASTER_LOG_FILE_NO_POS));
9588
9589
3/8
✓ Branch 0 taken 11242 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11242 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11242 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
11242 DBUG_PRINT("info", ("master_log_pos: %lu", (ulong)mi->get_master_log_pos()));
9590
9591
4/4
✓ Branch 0 taken 5595 times.
✓ Branch 1 taken 5647 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 5586 times.
11242 if (lex_mi->user || lex_mi->password) {
9592
3/4
✓ Branch 0 taken 5656 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5650 times.
✓ Branch 3 taken 6 times.
5656 if (!thd->get_ssl()) {
9593
2/4
✓ Branch 0 taken 5650 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5650 times.
✗ Branch 3 not taken.
5650 push_warning(thd, Sql_condition::SL_NOTE, ER_INSECURE_PLAIN_TEXT,
9594 ER_THD(thd, ER_INSECURE_PLAIN_TEXT));
9595 }
9596
2/4
✓ Branch 0 taken 5656 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5656 times.
✗ Branch 3 not taken.
5656 push_warning(thd, Sql_condition::SL_NOTE, ER_INSECURE_CHANGE_MASTER,
9597 ER_THD(thd, ER_INSECURE_CHANGE_MASTER));
9598 }
9599
9600
3/4
✓ Branch 0 taken 5647 times.
✓ Branch 1 taken 5595 times.
✓ Branch 2 taken 5647 times.
✗ Branch 3 not taken.
11242 if (lex_mi->user) mi->set_user(lex_mi->user);
9601
3/4
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 11047 times.
✓ Branch 2 taken 195 times.
✗ Branch 3 not taken.
11242 if (lex_mi->password) mi->set_password(lex_mi->password);
9602
3/4
✓ Branch 0 taken 8650 times.
✓ Branch 1 taken 2592 times.
✓ Branch 2 taken 8650 times.
✗ Branch 3 not taken.
11242 if (lex_mi->host) strmake(mi->host, lex_mi->host, sizeof(mi->host) - 1);
9603
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 11218 times.
11242 if (lex_mi->bind_addr)
9604
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 strmake(mi->bind_addr, lex_mi->bind_addr, sizeof(mi->bind_addr) - 1);
9605
9606
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11239 times.
11242 if (lex_mi->network_namespace)
9607
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 strmake(mi->network_namespace, lex_mi->network_namespace,
9608 sizeof(mi->network_namespace) - 1);
9609 /*
9610 Setting channel's port number explicitly to '0' should be allowed.
9611 Eg: 'group_replication_recovery' channel (*after recovery is done*)
9612 or 'group_replication_applier' channel wants to set the port number
9613 to '0' as there is no actual network usage on these channels.
9614 */
9615
4/4
✓ Branch 0 taken 6234 times.
✓ Branch 1 taken 5008 times.
✓ Branch 2 taken 3464 times.
✓ Branch 3 taken 2770 times.
11242 if (lex_mi->port || lex_mi->port_opt == LEX_MASTER_INFO::LEX_MI_ENABLE)
9616 8472 mi->port = lex_mi->port;
9617
2/2
✓ Branch 0 taken 3197 times.
✓ Branch 1 taken 8045 times.
11242 if (lex_mi->connect_retry) mi->connect_retry = lex_mi->connect_retry;
9618
2/2
✓ Branch 0 taken 2761 times.
✓ Branch 1 taken 8481 times.
11242 if (lex_mi->retry_count_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9619 2761 mi->retry_count = lex_mi->retry_count;
9620
9621
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 11163 times.
11242 if (lex_mi->heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9622 79 mi->heartbeat_period = lex_mi->heartbeat_period;
9623
4/4
✓ Branch 0 taken 2551 times.
✓ Branch 1 taken 8612 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 2518 times.
11163 else if (lex_mi->host || lex_mi->port) {
9624 /*
9625 If the user specified host or port or both without heartbeat_period,
9626 we use default value for heartbeat_period. By default, We want to always
9627 have heartbeat enabled when we switch master unless
9628 master_heartbeat_period is explicitly set to zero (heartbeat disabled).
9629
9630 Here is the default value for heartbeat period if CHANGE MASTER did not
9631 specify it. (no data loss in conversion as hb period has a max)
9632 */
9633 17290 mi->heartbeat_period = std::min<float>(SLAVE_MAX_HEARTBEAT_PERIOD,
9634 8645 (replica_net_timeout / 2.0f));
9635
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8645 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8645 assert(mi->heartbeat_period > (float)0.001 || mi->heartbeat_period == 0);
9636
9637 // counter is cleared if master is CHANGED.
9638 8645 mi->received_heartbeats = 0;
9639 // clear timestamp of last heartbeat as well.
9640 8645 mi->last_heartbeat = 0;
9641 }
9642
9643 /*
9644 reset the last time server_id list if the current CHANGE MASTER
9645 is mentioning IGNORE_SERVER_IDS= (...)
9646 */
9647
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 11205 times.
11242 if (lex_mi->repl_ignore_server_ids_opt == LEX_MASTER_INFO::LEX_MI_ENABLE)
9648
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 mi->ignore_server_ids->dynamic_ids.clear();
9649
3/4
✓ Branch 0 taken 11332 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✓ Branch 3 taken 11241 times.
11332 for (size_t i = 0; i < lex_mi->repl_ignore_server_ids.size(); i++) {
9650
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 ulong s_id = lex_mi->repl_ignore_server_ids[i];
9651
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
91 if (s_id == ::server_id && replicate_same_server_id) {
9652 1 ret = ER_SLAVE_IGNORE_SERVER_IDS;
9653
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SLAVE_IGNORE_SERVER_IDS, MYF(0), static_cast<int>(s_id));
9654 1 goto err;
9655 } else {
9656 // Keep the array sorted, ignore duplicates.
9657
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 mi->ignore_server_ids->dynamic_ids.insert_unique(s_id);
9658 }
9659 }
9660
9661
2/2
✓ Branch 0 taken 1395 times.
✓ Branch 1 taken 9846 times.
11241 if (lex_mi->ssl != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9662 1395 mi->ssl = (lex_mi->ssl == LEX_MASTER_INFO::LEX_MI_ENABLE);
9663
9664
2/2
✓ Branch 0 taken 1325 times.
✓ Branch 1 taken 9916 times.
11241 if (lex_mi->ssl_verify_server_cert != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9665 1325 mi->ssl_verify_server_cert =
9666 1325 (lex_mi->ssl_verify_server_cert == LEX_MASTER_INFO::LEX_MI_ENABLE);
9667
9668
2/2
✓ Branch 0 taken 1330 times.
✓ Branch 1 taken 9911 times.
11241 if (lex_mi->public_key_path)
9669
1/2
✓ Branch 0 taken 1330 times.
✗ Branch 1 not taken.
1330 strmake(mi->public_key_path, lex_mi->public_key_path,
9670 sizeof(mi->public_key_path) - 1);
9671
9672
2/2
✓ Branch 0 taken 2474 times.
✓ Branch 1 taken 8767 times.
11241 if (lex_mi->get_public_key != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
9673 2474 mi->get_public_key =
9674 2474 (lex_mi->get_public_key == LEX_MASTER_INFO::LEX_MI_ENABLE);
9675
9676
2/2
✓ Branch 0 taken 1345 times.
✓ Branch 1 taken 9896 times.
11241 if (lex_mi->ssl_ca)
9677
1/2
✓ Branch 0 taken 1345 times.
✗ Branch 1 not taken.
1345 strmake(mi->ssl_ca, lex_mi->ssl_ca, sizeof(mi->ssl_ca) - 1);
9678
2/2
✓ Branch 0 taken 1316 times.
✓ Branch 1 taken 9925 times.
11241 if (lex_mi->ssl_capath)
9679
1/2
✓ Branch 0 taken 1316 times.
✗ Branch 1 not taken.
1316 strmake(mi->ssl_capath, lex_mi->ssl_capath, sizeof(mi->ssl_capath) - 1);
9680
2/2
✓ Branch 0 taken 1322 times.
✓ Branch 1 taken 9919 times.
11241 if (lex_mi->tls_version)
9681
1/2
✓ Branch 0 taken 1322 times.
✗ Branch 1 not taken.
1322 strmake(mi->tls_version, lex_mi->tls_version, sizeof(mi->tls_version) - 1);
9682
9683
2/2
✓ Branch 0 taken 1309 times.
✓ Branch 1 taken 9932 times.
11241 if (LEX_MASTER_INFO::SPECIFIED_NULL == lex_mi->tls_ciphersuites) {
9684 1309 mi->tls_ciphersuites.first = true;
9685 1309 mi->tls_ciphersuites.second.clear();
9686
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 9912 times.
9932 } else if (LEX_MASTER_INFO::SPECIFIED_STRING == lex_mi->tls_ciphersuites) {
9687 20 mi->tls_ciphersuites.first = false;
9688
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 mi->tls_ciphersuites.second.assign(lex_mi->tls_ciphersuites_string);
9689 }
9690
9691
2/2
✓ Branch 0 taken 1345 times.
✓ Branch 1 taken 9896 times.
11241 if (lex_mi->ssl_cert)
9692
1/2
✓ Branch 0 taken 1345 times.
✗ Branch 1 not taken.
1345 strmake(mi->ssl_cert, lex_mi->ssl_cert, sizeof(mi->ssl_cert) - 1);
9693
2/2
✓ Branch 0 taken 1316 times.
✓ Branch 1 taken 9925 times.
11241 if (lex_mi->ssl_cipher)
9694
1/2
✓ Branch 0 taken 1316 times.
✗ Branch 1 not taken.
1316 strmake(mi->ssl_cipher, lex_mi->ssl_cipher, sizeof(mi->ssl_cipher) - 1);
9695
2/2
✓ Branch 0 taken 1345 times.
✓ Branch 1 taken 9896 times.
11241 if (lex_mi->ssl_key)
9696
1/2
✓ Branch 0 taken 1345 times.
✗ Branch 1 not taken.
1345 strmake(mi->ssl_key, lex_mi->ssl_key, sizeof(mi->ssl_key) - 1);
9697
2/2
✓ Branch 0 taken 1327 times.
✓ Branch 1 taken 9914 times.
11241 if (lex_mi->ssl_crl)
9698
1/2
✓ Branch 0 taken 1327 times.
✗ Branch 1 not taken.
1327 strmake(mi->ssl_crl, lex_mi->ssl_crl, sizeof(mi->ssl_crl) - 1);
9699
2/2
✓ Branch 0 taken 1327 times.
✓ Branch 1 taken 9914 times.
11241 if (lex_mi->ssl_crlpath)
9700
1/2
✓ Branch 0 taken 1327 times.
✗ Branch 1 not taken.
1327 strmake(mi->ssl_crlpath, lex_mi->ssl_crlpath, sizeof(mi->ssl_crlpath) - 1);
9701
9702
1/2
✓ Branch 0 taken 11241 times.
✗ Branch 1 not taken.
11241 ret = change_master_set_compression(thd, lex_mi, mi);
9703
2/2
✓ Branch 0 taken 11205 times.
✓ Branch 1 taken 36 times.
11241 if (ret) goto err;
9704
9705 11205 err:
9706 11242 return ret;
9707 11242 }
9708
9709 /**
9710 This function is called if the change master command had at least one
9711 execute option. This function then sets or alters the execute option(s)
9712 given in the command. The receive options are handled in the function
9713 change_receive_options()
9714
9715 - used in change_master().
9716 - Execute threads should be stopped before this function is called.
9717
9718 @param lex_mi structure that holds all change master options given on the
9719 change master command.
9720
9721 @param mi Pointer to Master_info object belonging to the replica channel
9722 that will be configured
9723
9724 @return false if the execute options were successfully set and true,
9725 otherwise.
9726 */
9727 3230 static bool change_execute_options(LEX_MASTER_INFO *lex_mi, Master_info *mi) {
9728
1/2
✓ Branch 0 taken 3230 times.
✗ Branch 1 not taken.
3230 DBUG_TRACE;
9729
9730
2/2
✓ Branch 0 taken 3190 times.
✓ Branch 1 taken 40 times.
3230 if (lex_mi->privilege_checks_username != nullptr ||
9731
2/2
✓ Branch 0 taken 2965 times.
✓ Branch 1 taken 225 times.
3190 lex_mi->privilege_checks_none) {
9732 Relay_log_info::enum_priv_checks_status error{
9733
1/2
✓ Branch 0 taken 3005 times.
✗ Branch 1 not taken.
3005 mi->rli->set_privilege_checks_user(
9734 lex_mi->privilege_checks_username,
9735
2/2
✓ Branch 0 taken 2965 times.
✓ Branch 1 taken 40 times.
3005 lex_mi->privilege_checks_none ? nullptr
9736 : lex_mi->privilege_checks_hostname)};
9737
2/4
✓ Branch 0 taken 3005 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3005 times.
3005 if (!!error) {
9738 mi->rli->report_privilege_check_error(
9739 ERROR_LEVEL, error, true /* to client*/, mi->rli->get_channel(),
9740 lex_mi->privilege_checks_username, lex_mi->privilege_checks_hostname);
9741 return true;
9742 }
9743 }
9744
9745
2/2
✓ Branch 0 taken 3016 times.
✓ Branch 1 taken 214 times.
3230 if (lex_mi->require_row_format != LEX_MASTER_INFO::LEX_MI_UNCHANGED) {
9746
1/2
✓ Branch 0 taken 3016 times.
✗ Branch 1 not taken.
3016 mi->rli->set_require_row_format(lex_mi->require_row_format ==
9747 LEX_MASTER_INFO::LEX_MI_ENABLE);
9748 }
9749
9750
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 3205 times.
3230 if (lex_mi->require_table_primary_key_check !=
9751 LEX_MASTER_INFO::LEX_MI_PK_CHECK_UNCHANGED) {
9752
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
25 switch (lex_mi->require_table_primary_key_check) {
9753 5 case (LEX_MASTER_INFO::LEX_MI_PK_CHECK_STREAM):
9754
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 mi->rli->set_require_table_primary_key_check(
9755 Relay_log_info::PK_CHECK_STREAM);
9756 5 break;
9757 8 case (LEX_MASTER_INFO::LEX_MI_PK_CHECK_ON):
9758
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 mi->rli->set_require_table_primary_key_check(
9759 Relay_log_info::PK_CHECK_ON);
9760 8 break;
9761 12 case (LEX_MASTER_INFO::LEX_MI_PK_CHECK_OFF):
9762
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 mi->rli->set_require_table_primary_key_check(
9763 Relay_log_info::PK_CHECK_OFF);
9764 12 break;
9765
9766 default: /* purecov: tested */
9767 assert(0); /* purecov: tested */
9768 break;
9769 }
9770 }
9771
9772
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 3171 times.
3230 if (lex_mi->relay_log_name) {
9773 char relay_log_name[FN_REFLEN];
9774
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 mi->rli->relay_log.make_log_name(relay_log_name, lex_mi->relay_log_name);
9775
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 mi->rli->set_group_relay_log_name(relay_log_name);
9776 59 mi->rli->is_group_master_log_pos_invalid = true;
9777 }
9778
9779
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 3185 times.
3230 if (lex_mi->relay_log_pos) {
9780 45 mi->rli->set_group_relay_log_pos(lex_mi->relay_log_pos);
9781 45 mi->rli->is_group_master_log_pos_invalid = true;
9782 }
9783
9784
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 3146 times.
3230 if (lex_mi->sql_delay != -1) mi->rli->set_sql_delay(lex_mi->sql_delay);
9785
9786 3230 return false;
9787 3230 }
9788
9789 /**
9790 This function is called if the change replication source command had at
9791 least one option that affects both the receiver and applier parts.
9792 Pure execute option(s) are handled in change_execute_options()
9793 The receive options are handled in the function change_receive_options()
9794
9795 - used in change_master().
9796 - Both receiver and applier threads should be stopped on invocation
9797
9798 @param lex_mi structure that holds all change replication source options
9799
9800 @param mi Pointer to Master_info object belonging to the replica channel
9801 to be configured
9802
9803 @return false if successfully set, true otherwise.
9804 */
9805 5937 static bool change_applier_receiver_options(THD *thd, LEX_MASTER_INFO *lex_mi,
9806 Master_info *mi) {
9807
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 5839 times.
5937 if (lex_mi->m_source_connection_auto_failover !=
9808 LEX_MASTER_INFO::LEX_MI_UNCHANGED) {
9809
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 if (lex_mi->m_source_connection_auto_failover ==
9810 LEX_MASTER_INFO::LEX_MI_ENABLE) {
9811 80 mi->set_source_connection_auto_failover();
9812 /*
9813 Send replication channel SOURCE_CONNECTION_AUTO_FAILOVER attribute of
9814 CHANGE REPLICATION SOURCE command status to group replication group
9815 members.
9816 */
9817
3/6
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 80 times.
160 if (rpl_acf_configuration_handler->send_channel_status_and_version_data(
9818 80 mi->get_channel(),
9819 Rpl_acf_status_configuration::SOURCE_CONNECTION_AUTO_FAILOVER,
9820 1)) {
9821 my_error(ER_GRP_RPL_FAILOVER_CHANNEL_STATUS_PROPAGATION, MYF(0),
9822 mi->get_channel());
9823 mi->unset_source_connection_auto_failover();
9824 return true;
9825 }
9826
9827 /*
9828 If IO thread is running and the monitoring thread is not, start
9829 the monitoring thread.
9830 */
9831
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 80 times.
80 if (mi->slave_running &&
9832
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
80 !Source_IO_monitor::get_instance()->is_monitoring_process_running()) {
9833 if (Source_IO_monitor::get_instance()->launch_monitoring_process(
9834 key_thread_replica_monitor_io)) {
9835 my_error(ER_STARTING_REPLICA_MONITOR_IO_THREAD, MYF(0));
9836 return true;
9837 }
9838 }
9839 } else {
9840 /*
9841 If this is the only channel with source_connection_auto_failover,
9842 then stop the monitoring thread.
9843 */
9844
4/6
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
18 if (mi->is_source_connection_auto_failover() && mi->slave_running &&
9845 channel_map
9846 .get_number_of_connection_auto_failover_channels_running() ==
9847 1) {
9848 if (Source_IO_monitor::get_instance()->terminate_monitoring_process()) {
9849 my_error(ER_STOP_REPLICA_MONITOR_IO_THREAD_TIMEOUT, MYF(0));
9850 return true;
9851 }
9852 }
9853 18 mi->unset_source_connection_auto_failover();
9854 /*
9855 Send replication channel SOURCE_CONNECTION_AUTO_FAILOVER attribute of
9856 CHANGE REPLICATION SOURCE command status to group replication group
9857 members.
9858 */
9859
3/6
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
36 if (rpl_acf_configuration_handler->send_channel_status_and_version_data(
9860 18 mi->get_channel(),
9861 Rpl_acf_status_configuration::SOURCE_CONNECTION_AUTO_FAILOVER,
9862 0)) {
9863 my_error(ER_GRP_RPL_FAILOVER_CHANNEL_STATUS_PROPAGATION, MYF(0),
9864 mi->get_channel());
9865 return true;
9866 }
9867 }
9868 }
9869
9870
2/2
✓ Branch 0 taken 5856 times.
✓ Branch 1 taken 81 times.
5937 if (lex_mi->auto_position != LEX_MASTER_INFO::LEX_MI_UNCHANGED) {
9871 5856 mi->set_auto_position(
9872 5856 (lex_mi->auto_position == LEX_MASTER_INFO::LEX_MI_ENABLE));
9873 }
9874
9875
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 5908 times.
5937 if (lex_mi->assign_gtids_to_anonymous_transactions_type !=
9876 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UNCHANGED) {
9877
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 11 times.
29 if (lex_mi->assign_gtids_to_anonymous_transactions_type >
9878 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_OFF) {
9879 18 push_warning(
9880 thd, Sql_condition::SL_NOTE,
9881 ER_USING_ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_AS_LOCAL_OR_UUID,
9882 ER_THD(
9883 thd,
9884 ER_USING_ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_AS_LOCAL_OR_UUID));
9885 }
9886
9887
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
29 switch (lex_mi->assign_gtids_to_anonymous_transactions_type) {
9888 12 case (LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_LOCAL):
9889 12 mi->rli->m_assign_gtids_to_anonymous_transactions_info.set_info(
9890 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_LOCAL,
9891 ::server_uuid);
9892 12 break;
9893 6 case (LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UUID):
9894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (mi->rli->m_assign_gtids_to_anonymous_transactions_info.set_info(
9895 Assign_gtids_to_anonymous_transactions_info::enum_type::
9896 AGAT_UUID,
9897 lex_mi->assign_gtids_to_anonymous_transactions_manual_uuid))
9898 return true;
9899 6 break;
9900 11 case (LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_OFF):
9901 11 mi->rli->m_assign_gtids_to_anonymous_transactions_info.set_info(
9902 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF,
9903 "");
9904 11 break;
9905 default:
9906 assert(0);
9907 break;
9908 }
9909 }
9910
9911
2/2
✓ Branch 0 taken 2967 times.
✓ Branch 1 taken 2970 times.
5937 if (lex_mi->m_gtid_only != LEX_MASTER_INFO::LEX_MI_UNCHANGED) {
9912 2967 mi->set_gtid_only_mode(
9913 2967 (lex_mi->m_gtid_only == LEX_MASTER_INFO::LEX_MI_ENABLE));
9914 }
9915
9916 5937 return false;
9917 }
9918
9919 /**
9920 This function shall issue a deprecation warning if
9921 there are server ids tokenized from the CHANGE MASTER
9922 TO command while @@global.gtid_mode=ON.
9923 */
9924 7848 static void issue_deprecation_warnings_for_channel(THD *thd) {
9925 7848 LEX_MASTER_INFO *lex_mi = &thd->lex->mi;
9926
9927 /*
9928 Deprecation of GTID_MODE + IGNORE_SERVER_IDS
9929
9930 Generate deprecation warning when user executes CHANGE
9931 MASTER TO IGNORE_SERVER_IDS if GTID_MODE=ON.
9932 */
9933
4/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 7824 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7846 times.
7872 if (lex_mi->repl_ignore_server_ids.size() > 0 &&
9934
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 global_gtid_mode.get() == Gtid_mode::ON) {
9935 2 push_warning_printf(thd, Sql_condition::SL_WARNING,
9936 ER_WARN_DEPRECATED_SYNTAX,
9937 ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT),
9938 "CHANGE MASTER TO ... IGNORE_SERVER_IDS='...' "
9939 "(when @@GLOBAL.GTID_MODE = ON)");
9940 }
9941 7848 }
9942
9943 /**
9944 This function validates that change replication source options are
9945 valid according to the current GTID_MODE.
9946 This method assumes it will only be called when GTID_MODE != ON
9947
9948 @param lex_mi structure that holds all change replication source options
9949
9950 @param mi Pointer to Master_info object belonging to the replica channel
9951 to be configured
9952
9953 @return false if the configuration is valid
9954 true some configuration option is invalid with GTID_MODE
9955 */
9956 3437 static int validate_gtid_option_restrictions(const LEX_MASTER_INFO *lex_mi,
9957 Master_info *mi) {
9958 3437 int error = 0;
9959
9960 /*
9961 CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION = 1 requires
9962 GTID_MODE != OFF
9963 */
9964
2/2
✓ Branch 0 taken 3376 times.
✓ Branch 1 taken 61 times.
3437 if (global_gtid_mode.get() == Gtid_mode::OFF) {
9965
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3364 times.
3376 if (lex_mi->auto_position == LEX_MASTER_INFO::LEX_MI_ENABLE) {
9966 12 error = ER_AUTO_POSITION_REQUIRES_GTID_MODE_NOT_OFF;
9967 12 my_error(ER_AUTO_POSITION_REQUIRES_GTID_MODE_NOT_OFF, MYF(0));
9968 12 return error;
9969 }
9970 }
9971
9972 /*
9973 CHANGE REPLICATION SOURCE TO ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS != OFF
9974 requires GTID_MODE = ON
9975 */
9976
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3424 times.
3425 if (lex_mi->assign_gtids_to_anonymous_transactions_type >
9977 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_OFF) {
9978 1 error = ER_ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_REQUIRES_GTID_MODE_ON;
9979 1 my_error(ER_ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS_REQUIRES_GTID_MODE_ON,
9980 MYF(0));
9981 1 return error;
9982 }
9983
9984 /*
9985 CHANGE REPLICATION SOURCE TO GTID_ONLY= 1 requires
9986 GTID_MODE = ON
9987 */
9988
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3423 times.
3424 if (lex_mi->m_gtid_only == LEX_MASTER_INFO::LEX_MI_ENABLE) {
9989 1 error = ER_CHANGE_REPLICATION_SOURCE_NO_OPTIONS_FOR_GTID_ONLY;
9990 1 my_error(ER_CHANGE_REPLICATION_SOURCE_NO_OPTIONS_FOR_GTID_ONLY, MYF(0),
9991 mi->get_channel());
9992 1 return error;
9993 }
9994
9995 /*
9996 CHANGE REPLICATION SOURCE TO SOURCE_CONNECTION_AUTO_FAILOVER = 1 requires
9997 GTID_MODE = ON
9998 */
9999
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3420 times.
3423 if (lex_mi->m_source_connection_auto_failover ==
10000 LEX_MASTER_INFO::LEX_MI_ENABLE) {
10001 3 error = ER_RPL_ASYNC_RECONNECT_GTID_MODE_OFF;
10002 3 my_error(ER_RPL_ASYNC_RECONNECT_GTID_MODE_OFF, MYF(0));
10003 3 return error;
10004 }
10005
10006
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3418 times.
3420 if (channel_map.is_group_replication_channel_name(lex_mi->channel)) {
10007 2 error = ER_CHANGE_REP_SOURCE_GR_CHANNEL_WITH_GTID_MODE_NOT_ON;
10008 2 my_error(error, MYF(0));
10009 2 return error;
10010 }
10011
10012 3418 return error;
10013 }
10014
10015 /**
10016 This is an helper method for boolean vars like
10017 SOURCE_AUTO_POSITION
10018 REQUIRE_ROW_FORMAT
10019 SOURCE_CONNECTION_AUTO_FAILOVER
10020 It tells if the variable is already enabled or will be by the command
10021
10022 @param base_value the current variable value
10023 @param option_value the configuration input value (UNCHANGED,ENABLED,DISABLE)
10024
10025 @return true if the option was already enable or will be. false otherwise
10026 */
10027 50824 bool is_option_enabled_or_will_be(bool base_value, int option_value) {
10028 50824 bool var_enabled = base_value;
10029
3/4
✓ Branch 0 taken 3017 times.
✓ Branch 1 taken 8949 times.
✓ Branch 2 taken 38858 times.
✗ Branch 3 not taken.
50824 switch (option_value) {
10030 3017 case LEX_MASTER_INFO::LEX_MI_ENABLE:
10031 3017 var_enabled = true;
10032 3017 break;
10033 8949 case LEX_MASTER_INFO::LEX_MI_DISABLE:
10034 8949 var_enabled = false;
10035 8949 break;
10036 38858 case LEX_MASTER_INFO::LEX_MI_UNCHANGED:
10037 38858 break;
10038 default:
10039 assert(0);
10040 break;
10041 }
10042 50824 return var_enabled;
10043 }
10044
10045 /**
10046 This method evaluates if the different options given to
10047 CHANGE REPLICATION SOURCE TO
10048 are compatible with the current configuration and with one another.
10049
10050 Example: SOURCE_CONNECTION_AUTO_FAILOVER = 1 requires
10051 SOURCE_AUTO_POSITION to be already enabled or to be enabled on this command.
10052
10053 @param lex_mi structure that holds all change replication source options given
10054 on the command
10055
10056 @param mi Pointer to Master_info object for the channel that holds the
10057 the configuration
10058
10059 @return 0 if no issues are found
10060 != 0 the error number associated to the issue, if one is found
10061 */
10062 12706 int evaluate_inter_option_dependencies(const LEX_MASTER_INFO *lex_mi,
10063 Master_info *mi) {
10064 12706 int error = 0;
10065
10066 /**
10067 We first define the variables used and then we group the checks for
10068 readability
10069 */
10070 12706 bool is_or_will_auto_position_be_enabled = is_option_enabled_or_will_be(
10071 12706 mi->is_auto_position(), lex_mi->auto_position);
10072 bool will_auto_position_be_disable =
10073
2/2
✓ Branch 0 taken 4547 times.
✓ Branch 1 taken 8159 times.
17253 mi->is_auto_position() &&
10074
2/2
✓ Branch 0 taken 1127 times.
✓ Branch 1 taken 3420 times.
4547 lex_mi->auto_position == LEX_MASTER_INFO::LEX_MI_DISABLE;
10075
10076 25412 bool is_or_will_require_row_format_be_enabled = is_option_enabled_or_will_be(
10077 12706 mi->rli->is_row_format_required(), lex_mi->require_row_format);
10078 bool will_require_row_format_be_disable =
10079
2/2
✓ Branch 0 taken 3321 times.
✓ Branch 1 taken 9385 times.
16027 mi->rli->is_row_format_required() &&
10080
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 3289 times.
3321 lex_mi->require_row_format == LEX_MASTER_INFO::LEX_MI_DISABLE;
10081
10082 bool is_or_will_source_connection_auto_failover_be_enabled =
10083 12706 is_option_enabled_or_will_be(mi->is_source_connection_auto_failover(),
10084 12706 lex_mi->m_source_connection_auto_failover);
10085
10086 38118 bool is_or_will_gtid_only_be_enabled = is_option_enabled_or_will_be(
10087 12706 mi->is_gtid_only_mode(), lex_mi->m_gtid_only);
10088 bool will_gtid_only_mode_be_disable =
10089
2/2
✓ Branch 0 taken 3276 times.
✓ Branch 1 taken 9430 times.
15982 mi->is_gtid_only_mode() &&
10090
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3263 times.
3276 lex_mi->m_gtid_only == LEX_MASTER_INFO::LEX_MI_DISABLE;
10091
10092 auto assign_gtids_to_anonymous_transactions_type =
10093 12706 mi->rli->m_assign_gtids_to_anonymous_transactions_info.get_type();
10094
4/5
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 12673 times.
✗ Branch 4 not taken.
12706 switch (lex_mi->assign_gtids_to_anonymous_transactions_type) {
10095 11 case LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_OFF:
10096 11 assign_gtids_to_anonymous_transactions_type =
10097 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF;
10098 11 break;
10099 13 case LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_LOCAL:
10100 13 assign_gtids_to_anonymous_transactions_type =
10101 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_LOCAL;
10102 13 break;
10103 9 case LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UUID:
10104 9 assign_gtids_to_anonymous_transactions_type =
10105 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_UUID;
10106 9 break;
10107 12673 case LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UNCHANGED:
10108 12673 break;
10109 default:
10110 assert(0);
10111 break;
10112 }
10113
10114 /* Check phase - enabling options */
10115
10116 /*
10117 We cannot specify auto position and set either the coordinates
10118 on source or replica. If we try to do so, an error message is
10119 printed out.
10120 */
10121
4/4
✓ Branch 0 taken 12640 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 12614 times.
✓ Branch 3 taken 26 times.
12706 if (lex_mi->log_file_name != nullptr || lex_mi->pos != 0 ||
10122
4/4
✓ Branch 0 taken 12555 times.
✓ Branch 1 taken 59 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 12551 times.
12614 lex_mi->relay_log_name != nullptr || lex_mi->relay_log_pos != 0) {
10123
4/4
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 152 times.
307 if (lex_mi->auto_position == LEX_MASTER_INFO::LEX_MI_ENABLE ||
10124
3/4
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 138 times.
290 (lex_mi->auto_position != LEX_MASTER_INFO::LEX_MI_DISABLE &&
10125 138 mi->is_auto_position())) {
10126 3 error = ER_BAD_SLAVE_AUTO_POSITION;
10127 3 my_error(error, MYF(0));
10128 3 return error;
10129 }
10130 }
10131
10132 /*
10133 CHANGE REPLICATION SOURCE TO ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS != OFF
10134 requires
10135 SOURCE_AUTO_POSITION = 0
10136 */
10137
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 12680 times.
12703 if (assign_gtids_to_anonymous_transactions_type !=
10138
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 21 times.
23 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF &&
10139 is_or_will_auto_position_be_enabled) {
10140 2 error = ER_CANT_COMBINE_ANONYMOUS_TO_GTID_AND_AUTOPOSITION;
10141 2 my_error(error, MYF(0));
10142 2 return error;
10143 }
10144
10145 /*
10146 CHANGE REPLICATION SOURCE TO GTID_ONLY = 1 requires
10147 SOURCE_AUTO_POSITION = 1
10148 REQUIRE_ROW_FORMAT = 1
10149 */
10150
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 12684 times.
12701 if (lex_mi->m_gtid_only == LEX_MASTER_INFO::LEX_MI_ENABLE &&
10151
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1 times.
17 (!is_or_will_auto_position_be_enabled ||
10152
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 15 times.
16 !is_or_will_require_row_format_be_enabled)) {
10153 2 error = ER_CHANGE_REPLICATION_SOURCE_NO_OPTIONS_FOR_GTID_ONLY;
10154 2 my_error(error, MYF(0), mi->get_channel());
10155 2 return error;
10156 }
10157
10158 /*
10159 CHANGE REPLICATION SOURCE TO SOURCE_CONNECTION_AUTO_FAILOVER = 1 requires
10160 SOURCE_AUTO_POSITION = 1
10161 */
10162
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 12612 times.
12699 if (lex_mi->m_source_connection_auto_failover ==
10163 87 LEX_MASTER_INFO::LEX_MI_ENABLE &&
10164
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 81 times.
87 !is_or_will_auto_position_be_enabled) {
10165 6 error = ER_RPL_ASYNC_RECONNECT_AUTO_POSITION_OFF;
10166 6 my_error(error, MYF(0));
10167 6 return error;
10168 }
10169
10170 /*
10171 We need to check if there is an empty master_host. Otherwise
10172 change master succeeds, a master.info file is created containing
10173 empty master_host string and when issuing: start replica; an error
10174 is thrown stating that the server is not configured as replica.
10175 (See BUG#28796).
10176 */
10177
4/4
✓ Branch 0 taken 8659 times.
✓ Branch 1 taken 4034 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8657 times.
12693 if (lex_mi->host && !*lex_mi->host) {
10178 2 error = ER_WRONG_ARGUMENTS;
10179 2 my_error(error, MYF(0), "MASTER_HOST");
10180 2 return error;
10181 }
10182
10183 /*
10184 Changing source_connection_auto_failover option is not allowed on group
10185 secondary member.
10186 */
10187 25382 if (lex_mi->m_source_connection_auto_failover !=
10188
4/4
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 12592 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12690 times.
12790 LEX_MASTER_INFO::LEX_MI_UNCHANGED &&
10189
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 98 times.
99 is_group_replication_member_secondary()) {
10190 1 error = ER_OPERATION_NOT_ALLOWED_ON_GR_SECONDARY;
10191 1 my_error(error, MYF(0));
10192 1 return error;
10193 }
10194
10195 /*
10196 CHANGE REPLICATION SOURCE TO ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS != OFF
10197 can't use the same value as the group replication name or view change uuid
10198 */
10199
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 12669 times.
12690 if (lex_mi->assign_gtids_to_anonymous_transactions_type >
10200 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_OFF) {
10201
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 std::string group_name = get_group_replication_group_name();
10202
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 13 times.
21 if (group_name.length() > 0) {
10203 8 bool is_same = false;
10204 8 auto type = lex_mi->assign_gtids_to_anonymous_transactions_type;
10205
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (type == LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_LOCAL)
10206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(group_name.compare(::server_uuid))) is_same = true;
10207
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (type == LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UUID)
10208
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (!(group_name.compare(
10209 6 lex_mi->assign_gtids_to_anonymous_transactions_manual_uuid)))
10210 2 is_same = true;
10211
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (is_same) {
10212 2 error = ER_CANT_USE_SAME_UUID_AS_GROUP_NAME;
10213
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(error, MYF(0));
10214 3 return error;
10215 }
10216
10217 6 std::string view_change_uuid;
10218
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (get_group_replication_view_change_uuid(view_change_uuid)) {
10219 /* purecov: begin inspected */
10220 error = ER_GRP_RPL_VIEW_CHANGE_UUID_FAIL_GET_VARIABLE;
10221 my_error(error, MYF(0));
10222 return error;
10223 /* purecov: end */
10224 } else {
10225
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (type == LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_LOCAL)
10226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!(view_change_uuid.compare(::server_uuid))) is_same = true;
10227
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (type == LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UUID)
10228
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (!(view_change_uuid.compare(
10229 4 lex_mi->assign_gtids_to_anonymous_transactions_manual_uuid)))
10230 1 is_same = true;
10231
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (is_same) {
10232 1 error = ER_CANT_USE_SAME_UUID_AS_VIEW_CHANGE_UUID;
10233
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(error, MYF(0));
10234 1 return error;
10235 }
10236 }
10237
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 }
10238
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 3 times.
21 }
10239
10240 /* Check phase - disabling options */
10241
10242 /*
10243 CHANGE REPLICATION SOURCE TO ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
10244 auto_position cannot be disable if either source_connection_auto_failover
10245 option is enabled or getting enabled in current CHANGE MASTER statement.
10246 */
10247
4/4
✓ Branch 0 taken 1124 times.
✓ Branch 1 taken 11563 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1121 times.
12687 if (will_auto_position_be_disable &&
10248 is_or_will_source_connection_auto_failover_be_enabled) {
10249 3 error = ER_DISABLE_AUTO_POSITION_REQUIRES_ASYNC_RECONNECT_OFF;
10250 3 my_error(error, MYF(0));
10251 3 return error;
10252 }
10253
10254 /*
10255 CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION = 0 cannot be done when
10256 GTID_ONLY = 1
10257 */
10258
4/4
✓ Branch 0 taken 1121 times.
✓ Branch 1 taken 11563 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1120 times.
12684 if (will_auto_position_be_disable && is_or_will_gtid_only_be_enabled) {
10259 1 error = ER_CHANGE_REP_SOURCE_CANT_DISABLE_AUTO_POSITION_WITH_GTID_ONLY;
10260 1 my_error(error, MYF(0), mi->get_channel());
10261 1 return error;
10262 }
10263 /*
10264 CHANGE REPLICATION SOURCE TO REQUIRE_ROW_FORMAT = 0 cannot be done when
10265 GTID_ONLY = 1
10266 */
10267
4/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 12651 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 31 times.
12683 if (will_require_row_format_be_disable && is_or_will_gtid_only_be_enabled) {
10268 1 error = ER_CHANGE_REP_SOURCE_CANT_DISABLE_REQ_ROW_FORMAT_WITH_GTID_ONLY;
10269 1 my_error(error, MYF(0), mi->get_channel());
10270 1 return error;
10271 }
10272
10273 /*
10274 CHANGE REPLICATION SOURCE TO SOURCE_AUTO_POSITION = 0 when
10275 source positions in relation to the source are invalid.
10276 This requires `SOURCE_LOG_FILE` and `SOURCE_LOG_POS`
10277 The message varies if you are also disabling `GTID_ONLY`
10278 */
10279
2/2
✓ Branch 0 taken 1120 times.
✓ Branch 1 taken 11562 times.
12682 if (will_auto_position_be_disable) {
10280
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1116 times.
1120 if (mi->is_receiver_position_info_invalid()) {
10281
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
4 if (lex_mi->log_file_name == nullptr || lex_mi->pos == 0) {
10282
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (will_gtid_only_mode_be_disable) {
10283 1 error = ER_CHANGE_REP_SOURCE_CANT_DISABLE_GTID_ONLY_WITHOUT_POSITIONS;
10284 1 my_error(error, MYF(0), mi->get_channel());
10285 } else {
10286 1 error = ER_CHANGE_REP_SOURCE_CANT_DISABLE_AUTO_POS_WITHOUT_POSITIONS;
10287 1 my_error(error, MYF(0), mi->get_channel());
10288 }
10289 2 return error;
10290 }
10291 }
10292 }
10293 12680 return error;
10294 }
10295
10296 /**
10297 Log a warning in case GTID_ONLY or SOURCE AUTO POSITION are disabled
10298 and the server contains invalid positions.
10299
10300 @param thd the associated thread object
10301
10302 @param lex_mi structure that holds all change replication source options given
10303 on the command
10304
10305 @param mi Pointer to Master_info object
10306 */
10307 12634 static void log_invalid_position_warning(THD *thd,
10308 const LEX_MASTER_INFO *lex_mi,
10309 Master_info *mi) {
10310
2/2
✓ Branch 0 taken 9682 times.
✓ Branch 1 taken 2952 times.
12634 if (lex_mi->m_gtid_only == LEX_MASTER_INFO::LEX_MI_DISABLE ||
10311
2/2
✓ Branch 0 taken 1148 times.
✓ Branch 1 taken 8534 times.
9682 lex_mi->auto_position == LEX_MASTER_INFO::LEX_MI_DISABLE) {
10312
4/4
✓ Branch 0 taken 4098 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 4097 times.
8198 if (mi->is_receiver_position_info_invalid() ||
10313
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4097 times.
4098 mi->rli->is_applier_source_position_info_invalid()) {
10314 3 push_warning_printf(
10315 thd, Sql_condition::SL_WARNING,
10316 ER_WARN_C_DISABLE_GTID_ONLY_WITH_SOURCE_AUTO_POS_INVALID_POS,
10317 ER_THD(thd,
10318 ER_WARN_C_DISABLE_GTID_ONLY_WITH_SOURCE_AUTO_POS_INVALID_POS),
10319 mi->get_channel());
10320
7/14
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
3 LogErr(WARNING_LEVEL,
10321 ER_WARN_L_DISABLE_GTID_ONLY_WITH_SOURCE_AUTO_POS_INVALID_POS,
10322 mi->get_channel());
10323 }
10324 }
10325 12634 }
10326
10327 /**
10328 This method aggregates the validation checks made for the command
10329 CHANGE REPLICATION SOURCE
10330
10331 @param thd Pointer to THD object for the client thread executing the
10332 statement.
10333
10334 @param lex_mi structure that holds all change replication source options given
10335 on the command
10336
10337 @param mi Pointer to Master_info object for the channel that holds the
10338 the configuration
10339
10340 @param thread_mask The thread mask identifying which threads are running
10341
10342 @return A pair of booleans <return_value, remove_mta_info>
10343 return_value: true if an error occurred, false otherwise
10344 remove_mta_info: if true remove MTA worker info
10345 */
10346 12677 static std::pair<bool, bool> validate_change_replication_source_options(
10347 THD *thd, const LEX_MASTER_INFO *lex_mi, Master_info *mi, int thread_mask) {
10348 12677 bool mta_remove_worker_info = false;
10349
2/2
✓ Branch 0 taken 12650 times.
✓ Branch 1 taken 27 times.
12677 if ((thread_mask & SLAVE_SQL) == 0) // If execute threads are stopped
10350 {
10351
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12648 times.
12650 if (mi->rli->mts_recovery_group_cnt) {
10352 /*
10353 Change-Master can't be done if there is a mts group gap.
10354 That requires mts-recovery which START SLAVE provides.
10355 */
10356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(mi->rli->recovery_parallel_workers);
10357
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_MTS_CHANGE_MASTER_CANT_RUN_WITH_GAPS, MYF(0));
10358
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return std::make_pair(true, mta_remove_worker_info);
10359 } else {
10360 /*
10361 Lack of mts group gaps makes Workers info stale regardless of
10362 need_relay_log_purge computation. We set the mta_remove_worker_info
10363 flag here and call reset_workers() later to delete the worker info
10364 in mysql.slave_worker_info table.
10365 */
10366
2/2
✓ Branch 0 taken 1360 times.
✓ Branch 1 taken 11288 times.
12648 if (mi->rli->recovery_parallel_workers) mta_remove_worker_info = true;
10367 }
10368 }
10369
10370 /*
10371 When give a warning?
10372 CHANGE MASTER command is used in three ways:
10373 a) To change a connection configuration but remain connected to
10374 the same master.
10375 b) To change positions in binary or relay log(eg: master_log_pos).
10376 c) To change the master you are replicating from.
10377 We give a warning in cases b and c.
10378 */
10379
6/6
✓ Branch 0 taken 3992 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 3964 times.
✓ Branch 3 taken 28 times.
✓ Branch 4 taken 3945 times.
✓ Branch 5 taken 19 times.
4025 if ((lex_mi->host || lex_mi->port || lex_mi->log_file_name || lex_mi->pos ||
10380
10/10
✓ Branch 0 taken 4025 times.
✓ Branch 1 taken 8650 times.
✓ Branch 2 taken 3898 times.
✓ Branch 3 taken 47 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 3894 times.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 8775 times.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 12669 times.
25401 lex_mi->relay_log_name || lex_mi->relay_log_pos) &&
10381 8781 (mi->rli->atomic_channel_open_temp_tables > 0))
10382
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 push_warning(thd, Sql_condition::SL_WARNING,
10383 ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO,
10384 ER_THD(thd, ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO));
10385
10386 /**
10387 Although this check is redone when the user is set, we do an early
10388 check here to avoid failures in the middle of configuration
10389 */
10390 Relay_log_info::enum_priv_checks_status priv_check_error;
10391 12675 priv_check_error = mi->rli->check_privilege_checks_user(
10392
1/2
✓ Branch 0 taken 12675 times.
✗ Branch 1 not taken.
12675 lex_mi->privilege_checks_username,
10393
2/2
✓ Branch 0 taken 2965 times.
✓ Branch 1 taken 9710 times.
12675 lex_mi->privilege_checks_none ? nullptr
10394 : lex_mi->privilege_checks_hostname);
10395
2/4
✓ Branch 0 taken 12675 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12675 times.
12675 if (!!priv_check_error) {
10396 mi->rli->report_privilege_check_error(
10397 ERROR_LEVEL, priv_check_error, true /* to client*/,
10398 mi->rli->get_channel(), lex_mi->privilege_checks_username,
10399 lex_mi->privilege_checks_hostname);
10400 return std::make_pair(true, mta_remove_worker_info);
10401 }
10402
1/2
✓ Branch 0 taken 12675 times.
✗ Branch 1 not taken.
12675 return std::make_pair(false, mta_remove_worker_info);
10403 }
10404
10405 /**
10406 This method aggregates the the instantiation of options for the command
10407 CHANGE REPLICATION SOURCE
10408
10409 @param thd Pointer to THD object for the client thread executing the
10410 statement.
10411
10412 @param lex_mi structure that holds all change replication source options given
10413 on the command
10414
10415 @param mi Pointer to Master_info object belonging to the replica channel
10416 to be configured
10417
10418 @param have_both_receive_execute_option the command will change options that
10419 affect both the applier and receiver
10420
10421 @param have_execute_option the command will change applier related options
10422
10423 @param have_receive_option the command will change receiver related options
10424
10425 @return returns true if an error occurred, false otherwise
10426 */
10427 12675 static bool update_change_replication_source_options(
10428 THD *thd, LEX_MASTER_INFO *lex_mi, Master_info *mi,
10429 bool have_both_receive_execute_option, bool have_execute_option,
10430 bool have_receive_option) {
10431
2/2
✓ Branch 0 taken 5937 times.
✓ Branch 1 taken 6738 times.
12675 if (have_both_receive_execute_option) {
10432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5937 times.
5937 if (change_applier_receiver_options(thd, lex_mi, mi)) {
10433 return true;
10434 }
10435 }
10436
10437
2/2
✓ Branch 0 taken 6643 times.
✓ Branch 1 taken 6032 times.
12675 if (channel_map.is_group_replication_channel_name(lex_mi->channel)) {
10438 6643 mi->set_auto_position(true);
10439 6643 mi->rli->set_require_row_format(true);
10440 6643 mi->set_gtid_only_mode(true);
10441 }
10442
10443
4/6
✓ Branch 0 taken 3230 times.
✓ Branch 1 taken 9445 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3230 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12675 times.
12675 if (have_execute_option && change_execute_options(lex_mi, mi)) return true;
10444
10445
2/2
✓ Branch 0 taken 11242 times.
✓ Branch 1 taken 1433 times.
12675 if (have_receive_option) {
10446
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 11205 times.
11242 if (change_receive_options(thd, lex_mi, mi)) {
10447 37 return true;
10448 }
10449 }
10450
10451 12638 return false;
10452 }
10453
10454 /**
10455 Execute a CHANGE MASTER statement.
10456
10457 Apart from changing the receive/execute configurations/positions,
10458 this function also does the following:
10459 - May leave replicated open temporary table after warning.
10460 - Purges relay logs if no threads running and no relay log file/pos options.
10461 - Delete worker info in mysql.slave_worker_info table if applier not running.
10462
10463 @param thd Pointer to THD object for the client thread executing
10464 the statement.
10465
10466 @param mi Pointer to Master_info object belonging to the slave's
10467 IO thread.
10468
10469 @param lex_mi Lex information with master connection data.
10470 Coming from the an executing statement or set directly
10471 this shall contain connection settings like hostname,
10472 user, password and other settings like the number of
10473 connection retries.
10474
10475 @param preserve_logs If the decision of purging the logs should be always be
10476 false even if no relay log name/position is given to
10477 the method. The preserve_logs parameter will not be
10478 respected when the relay log info repository is not
10479 initialized.
10480
10481 @retval 0 success
10482 @retval !=0 error
10483 */
10484 12785 int change_master(THD *thd, Master_info *mi, LEX_MASTER_INFO *lex_mi,
10485 bool preserve_logs) {
10486 12785 int error = 0;
10487
10488 /* Do we have at least one receive related (IO thread) option? */
10489 12785 bool have_receive_option = false;
10490 /* Do we have at least one execute related (SQL/coord/worker) option? */
10491 12785 bool have_execute_option = false;
10492 /* Do we have at least one option that relates to receival and execution? */
10493 12785 bool have_both_receive_execute_option = false;
10494 /** Is there a an error during validation */
10495 12785 bool validation_error = false;
10496 /* If there are no mts gaps, we delete the rows in this table. */
10497 12785 bool mta_remove_worker_info = false;
10498 /* used as a bit mask to indicate running slave threads. */
10499 int thread_mask;
10500 /*
10501 Relay logs are purged only if both receive and execute threads are
10502 stopped before executing CHANGE MASTER and relay_log_file/relay_log_pos
10503 options are not used.
10504 */
10505 12785 bool need_relay_log_purge = true;
10506
10507 /*
10508 We want to save the old receive configurations so that we can use them to
10509 print the changes in these configurations (from-to form). This is used in
10510 LogErr() later.
10511 */
10512 char saved_host[HOSTNAME_LENGTH + 1], saved_bind_addr[HOSTNAME_LENGTH + 1];
10513 12785 uint saved_port = 0;
10514 char saved_log_name[FN_REFLEN];
10515 12785 my_off_t saved_log_pos = 0;
10516
10517
1/2
✓ Branch 0 taken 12785 times.
✗ Branch 1 not taken.
12785 DBUG_TRACE;
10518
10519 /*
10520 CHANGE MASTER command should ignore 'read-only' and 'super_read_only'
10521 options so that it can update 'mysql.slave_master_info' replication
10522 repository tables.
10523 */
10524 12785 thd->set_skip_readonly_check();
10525
1/2
✓ Branch 0 taken 12785 times.
✗ Branch 1 not taken.
12785 mi->channel_wrlock();
10526 /*
10527 When we change master, we first decide which thread is running and
10528 which is not. We dont want this assumption to break while we change master.
10529
10530 Suppose we decide that receiver thread is running and thus it is
10531 safe to change receive related options in mi. By this time if
10532 the receive thread is started, we may have a race condition between
10533 the client thread and receiver thread.
10534 */
10535
1/2
✓ Branch 0 taken 12785 times.
✗ Branch 1 not taken.
12785 lock_slave_threads(mi);
10536
10537 /*
10538 Get a bit mask for the slave threads that are running.
10539 Since the third argument is 0, thread_mask after the function
10540 returns stands for running threads.
10541 */
10542
1/2
✓ Branch 0 taken 12785 times.
✗ Branch 1 not taken.
12785 init_thread_mask(&thread_mask, mi, false);
10543
10544
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 12661 times.
12785 if (thread_mask) /* If any thread is running */
10545 {
10546 /*
10547 Prior to WL#6120, we imposed the condition that STOP SLAVE is required
10548 before CHANGE MASTER. Since the slave threads die on STOP SLAVE, it was
10549 fine if we purged relay logs.
10550
10551 Now that we do allow CHANGE MASTER with a running receiver/applier thread,
10552 we need to make sure that the relay logs are purged only if both
10553 receiver and applier threads are stopped otherwise we could lose events.
10554
10555 The idea behind purging relay logs if both the threads are stopped is to
10556 keep consistency with the old behavior. If the user/application is doing
10557 a CHANGE MASTER without stopping any one thread, the relay log purge
10558 should be controlled via the 'relay_log_purge' option.
10559 */
10560 124 need_relay_log_purge = false;
10561 }
10562
10563 /* Check if at least one receive option is given on change master */
10564
1/2
✓ Branch 0 taken 12785 times.
✗ Branch 1 not taken.
12785 have_receive_option = have_change_replication_source_receive_option(lex_mi);
10565
10566 /* Check if at least one execute option is given on change master */
10567
1/2
✓ Branch 0 taken 12785 times.
✗ Branch 1 not taken.
12785 have_execute_option = have_change_replication_source_execute_option(
10568 lex_mi, &need_relay_log_purge);
10569 /* Check if at least one execute option affects both the applier and receiver
10570 */
10571 have_both_receive_execute_option =
10572
1/2
✓ Branch 0 taken 12785 times.
✗ Branch 1 not taken.
12785 have_change_replication_source_applier_and_receive_option(lex_mi);
10573
10574 /* If either:
10575 + An option affects both the applier and receiver and one of the threads
10576 is running
10577 + There are receiver and applier options and both threads are running
10578 Then tell the user the replica must stop
10579 */
10580
2/2
✓ Branch 0 taken 5987 times.
✓ Branch 1 taken 6798 times.
12785 if ((have_both_receive_execute_option &&
10581
6/6
✓ Branch 0 taken 5981 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 5978 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 11299 times.
✓ Branch 5 taken 1477 times.
12785 ((thread_mask & SLAVE_IO) || (thread_mask & SLAVE_SQL))) ||
10582
4/4
✓ Branch 0 taken 3073 times.
✓ Branch 1 taken 8226 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 3053 times.
11299 (have_receive_option && have_execute_option && (thread_mask & SLAVE_IO) &&
10583
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 17 times.
20 (thread_mask & SLAVE_SQL))) {
10584 12 error = ER_SLAVE_CHANNEL_MUST_STOP;
10585
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_error(ER_SLAVE_CHANNEL_MUST_STOP, MYF(0), mi->get_channel());
10586 12 goto err;
10587 }
10588
10589 /* With receiver thread running, we dont allow changing receive options. */
10590
4/4
✓ Branch 0 taken 11296 times.
✓ Branch 1 taken 1477 times.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 11262 times.
12773 if (have_receive_option && (thread_mask & SLAVE_IO)) {
10591 34 error = ER_SLAVE_CHANNEL_IO_THREAD_MUST_STOP;
10592
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 my_error(ER_SLAVE_CHANNEL_IO_THREAD_MUST_STOP, MYF(0), mi->get_channel());
10593 34 goto err;
10594 }
10595
10596 /* With an execute thread running, we don't allow changing execute options. */
10597
4/4
✓ Branch 0 taken 3249 times.
✓ Branch 1 taken 9490 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 3235 times.
12739 if (have_execute_option && (thread_mask & SLAVE_SQL)) {
10598 14 error = ER_SLAVE_CHANNEL_SQL_THREAD_MUST_STOP;
10599
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 my_error(ER_SLAVE_CHANNEL_SQL_THREAD_MUST_STOP, MYF(0), mi->get_channel());
10600 14 goto err;
10601 }
10602
10603 /* If GTID_MODE is different from ON check if some options are invalid
10604 We hold channel_map lock for the duration of the CHANGE MASTER.
10605 This is important since it prevents that a concurrent
10606 connection changes to GTID_MODE=OFF between this check and the
10607 point where AUTO_POSITION is stored in the table and in mi.
10608 */
10609
3/4
✓ Branch 0 taken 12725 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3437 times.
✓ Branch 3 taken 9288 times.
12725 if (global_gtid_mode.get() != Gtid_mode::ON) {
10610
3/4
✓ Branch 0 taken 3437 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 3418 times.
3437 if ((error = validate_gtid_option_restrictions(lex_mi, mi))) {
10611 19 goto err;
10612 }
10613 }
10614
10615
3/4
✓ Branch 0 taken 12706 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 12680 times.
12706 if ((error = evaluate_inter_option_dependencies(lex_mi, mi))) {
10616 26 goto err;
10617 }
10618
10619
4/4
✓ Branch 0 taken 12558 times.
✓ Branch 1 taken 122 times.
✓ Branch 2 taken 2247 times.
✓ Branch 3 taken 10311 times.
12680 if (need_relay_log_purge && /* If we should purge the logs for this channel */
10620 2247 preserve_logs && /* And we were asked to keep them */
10621
2/2
✓ Branch 0 taken 592 times.
✓ Branch 1 taken 1655 times.
2247 mi->rli->inited) /* And the channel was initialized properly */
10622 {
10623 592 need_relay_log_purge = false;
10624 }
10625
10626
1/2
✓ Branch 0 taken 12680 times.
✗ Branch 1 not taken.
12680 THD_STAGE_INFO(thd, stage_changing_source);
10627
10628 int thread_mask_stopped_threads;
10629
10630 /*
10631 Before load_mi_and_rli_from_repositories() call, get a bit mask to indicate
10632 stopped threads in thread_mask_stopped_threads. Since the third argguement
10633 is 1, thread_mask when the function returns stands for stopped threads.
10634 */
10635
10636
1/2
✓ Branch 0 taken 12680 times.
✗ Branch 1 not taken.
12680 init_thread_mask(&thread_mask_stopped_threads, mi, true);
10637
10638
3/4
✓ Branch 0 taken 12680 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 12677 times.
12680 if (load_mi_and_rli_from_repositories(mi, false, thread_mask_stopped_threads,
10639 need_relay_log_purge)) {
10640 3 error = ER_MASTER_INFO;
10641
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_MASTER_INFO, MYF(0));
10642 3 goto err;
10643 }
10644
10645 12677 std::tie(validation_error, mta_remove_worker_info) =
10646
1/2
✓ Branch 0 taken 12677 times.
✗ Branch 1 not taken.
25354 validate_change_replication_source_options(thd, lex_mi, mi, thread_mask);
10647
10648
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12675 times.
12677 if (validation_error) {
10649 2 error = 1;
10650 2 goto err;
10651 }
10652
10653 /*
10654 Validation operations should be above this comment
10655 Try to use the validate_change_replication_source_options method
10656
10657 Changes to variables should be below this comment
10658 Try to use the update_change_replication_source_options method
10659 */
10660
10661
2/2
✓ Branch 0 taken 11242 times.
✓ Branch 1 taken 1433 times.
12675 if (have_receive_option) {
10662
1/2
✓ Branch 0 taken 11242 times.
✗ Branch 1 not taken.
11242 strmake(saved_host, mi->host, HOSTNAME_LENGTH);
10663
1/2
✓ Branch 0 taken 11242 times.
✗ Branch 1 not taken.
11242 strmake(saved_bind_addr, mi->bind_addr, HOSTNAME_LENGTH);
10664 11242 saved_port = mi->port;
10665
1/2
✓ Branch 0 taken 11242 times.
✗ Branch 1 not taken.
11242 strmake(saved_log_name, mi->get_master_log_name(), FN_REFLEN - 1);
10666 11242 saved_log_pos = mi->get_master_log_pos();
10667 }
10668
10669
3/4
✓ Branch 0 taken 12675 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 12638 times.
12675 if (update_change_replication_source_options(
10670 thd, lex_mi, mi, have_both_receive_execute_option,
10671 have_execute_option, have_receive_option)) {
10672 37 error = 1;
10673 37 goto err;
10674 }
10675
10676 /*
10677 If user didn't specify neither host nor port nor any log name nor any log
10678 pos, i.e. he specified only user/password/master_connect_retry,
10679 master_delay, he probably wants replication to resume from where it had
10680 left, i.e. from the coordinates of the **SQL** thread (imagine the case
10681 where the I/O is ahead of the SQL; restarting from the coordinates of the
10682 I/O would lose some events which is probably unwanted when you are just
10683 doing minor changes like changing master_connect_retry). Note: coordinates
10684 of the SQL thread must be read before the block which resets them.
10685 */
10686
2/2
✓ Branch 0 taken 11925 times.
✓ Branch 1 taken 713 times.
12638 if (need_relay_log_purge) {
10687 /*
10688 A side-effect is that if only the I/O thread was started, this thread may
10689 restart from ''/4 after the CHANGE MASTER. That's a minor problem (it is a
10690 much more unlikely situation than the one we are fixing here).
10691 */
10692
4/4
✓ Branch 0 taken 3891 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 3869 times.
✓ Branch 3 taken 22 times.
3924 if (!lex_mi->host && !lex_mi->port && !lex_mi->log_file_name &&
10693
9/10
✓ Branch 0 taken 3924 times.
✓ Branch 1 taken 8001 times.
✓ Branch 2 taken 3850 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 3850 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3841 times.
✓ Branch 7 taken 9 times.
✓ Branch 8 taken 3841 times.
✓ Branch 9 taken 8084 times.
15849 !lex_mi->pos && !mi->rli->is_applier_source_position_info_invalid()) {
10694 /*
10695 Sometimes mi->rli->master_log_pos == 0 (it happens when the SQL thread
10696 is not initialized), so we use a max(). What happens to
10697 mi->rli->master_log_pos during the initialization stages of replication
10698 is not 100% clear, so we guard against problems using max().
10699 */
10700 3841 mi->set_master_log_pos(max<ulonglong>(
10701 3841 BIN_LOG_HEADER_SIZE, mi->rli->get_group_master_log_pos()));
10702
1/2
✓ Branch 0 taken 3841 times.
✗ Branch 1 not taken.
3841 mi->set_master_log_name(mi->rli->get_group_master_log_name());
10703 }
10704 }
10705
10706
2/2
✓ Branch 0 taken 11205 times.
✓ Branch 1 taken 1433 times.
12638 if (have_receive_option)
10707
9/18
✓ Branch 0 taken 11205 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11205 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11205 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11205 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11205 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11205 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11205 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 11205 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11205 times.
✗ Branch 17 not taken.
11205 LogErr(SYSTEM_LEVEL, ER_SLAVE_CHANGE_MASTER_TO_EXECUTED,
10708 mi->get_for_channel_str(true), saved_host, saved_port,
10709 saved_log_name, (ulong)saved_log_pos, saved_bind_addr, mi->host,
10710 mi->port, mi->get_master_log_name(), (ulong)mi->get_master_log_pos(),
10711 mi->bind_addr);
10712
10713 /* If the receiver is stopped, flush master_info to disk. */
10714
5/8
✓ Branch 0 taken 12601 times.
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 12601 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12601 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12638 times.
12638 if ((thread_mask & SLAVE_IO) == 0 && flush_master_info(mi, true)) {
10715 error = ER_RELAY_LOG_INIT;
10716 my_error(ER_RELAY_LOG_INIT, MYF(0), "Failed to flush master info file");
10717 goto err;
10718 }
10719
10720
2/2
✓ Branch 0 taken 12611 times.
✓ Branch 1 taken 27 times.
12638 if ((thread_mask & SLAVE_SQL) == 0) /* Applier module is not executing */
10721 {
10722
2/2
✓ Branch 0 taken 11925 times.
✓ Branch 1 taken 686 times.
12611 if (need_relay_log_purge) {
10723 /*
10724 'if (need_relay_log_purge)' implicitly means that all slave threads are
10725 stopped and there is no use of relay_log_file/relay_log_pos options.
10726 We need not check these here again.
10727 */
10728
10729 /* purge_relay_log() returns pointer to an error message here. */
10730 11925 const char *errmsg = nullptr;
10731 /*
10732 purge_relay_log() assumes that we have run_lock and no slave threads
10733 are running.
10734 */
10735
1/2
✓ Branch 0 taken 11925 times.
✗ Branch 1 not taken.
11925 THD_STAGE_INFO(thd, stage_purging_old_relay_logs);
10736
3/4
✓ Branch 0 taken 11925 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 11922 times.
11925 if (mi->rli->purge_relay_logs(thd, &errmsg)) {
10737 3 error = ER_RELAY_LOG_FAIL;
10738
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_RELAY_LOG_FAIL, MYF(0), errmsg);
10739 3 goto err;
10740 }
10741
10742 /*
10743 Coordinates in rli were spoilt by purge_relay_logs(),
10744 so restore them to good values. If we left them to ''/0, that would
10745 work. But that would fail in the case of 2 successive CHANGE MASTER
10746 (without a START SLAVE in between): because first one would set the
10747 coords in mi to the good values of those in rli, then set those i>n rli
10748 to ''/0, then second CHANGE MASTER would set the coords in mi to those
10749 of rli, i.e. to ''/0: we have lost all copies of the original good
10750 coordinates. That's why we always save good coords in rli.
10751 */
10752
3/4
✓ Branch 0 taken 11922 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11915 times.
✓ Branch 3 taken 7 times.
11922 if (!mi->is_receiver_position_info_invalid()) {
10753 11915 mi->rli->set_group_master_log_pos(mi->get_master_log_pos());
10754
1/2
✓ Branch 0 taken 11915 times.
✗ Branch 1 not taken.
11915 mi->rli->set_group_master_log_name(mi->get_master_log_name());
10755
3/8
✓ Branch 0 taken 11915 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11915 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11915 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
11915 DBUG_PRINT("info", ("master_log_pos: %llu", mi->get_master_log_pos()));
10756 }
10757 } else {
10758 686 const char *errmsg = nullptr;
10759
2/4
✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 686 times.
686 if (mi->rli->is_group_relay_log_name_invalid(&errmsg)) {
10760 error = ER_RELAY_LOG_INIT;
10761 my_error(ER_RELAY_LOG_INIT, MYF(0), errmsg);
10762 goto err;
10763 }
10764 }
10765
10766 char *var_group_master_log_name =
10767 12608 const_cast<char *>(mi->rli->get_group_master_log_name());
10768
10769
4/4
✓ Branch 0 taken 11636 times.
✓ Branch 1 taken 972 times.
✓ Branch 2 taken 11517 times.
✓ Branch 3 taken 1091 times.
24244 if (!var_group_master_log_name[0] && // uninitialized case
10770
3/4
✓ Branch 0 taken 11636 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11517 times.
✓ Branch 3 taken 119 times.
11636 !mi->rli->is_applier_source_position_info_invalid())
10771 11517 mi->rli->set_group_master_log_pos(0);
10772
10773 12608 mi->rli->abort_pos_wait++; /* for SOURCE_POS_WAIT() to abort */
10774
10775 /* Clear the errors, for a clean start */
10776
1/2
✓ Branch 0 taken 12608 times.
✗ Branch 1 not taken.
12608 mi->rli->clear_error();
10777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12608 times.
12608 if (mi->rli->workers_array_initialized) {
10778 for (size_t i = 0; i < mi->rli->get_worker_count(); i++) {
10779 mi->rli->get_worker(i)->clear_error();
10780 }
10781 }
10782
10783 /*
10784 If we don't write new coordinates to disk now, then old will remain in
10785 relay-log.info until START SLAVE is issued; but if mysqld is shutdown
10786 before START SLAVE, then old will remain in relay-log.info, and will be
10787 the in-memory value at restart (thus causing errors, as the old relay log
10788 does not exist anymore).
10789
10790 Notice that the rli table is available exclusively as slave is not
10791 running.
10792 */
10793
3/4
✓ Branch 0 taken 12608 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12607 times.
12608 if (mi->rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT |
10794 Relay_log_info::RLI_FLUSH_IGNORE_GTID_ONLY)) {
10795 1 error = ER_RELAY_LOG_INIT;
10796
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_RELAY_LOG_INIT, MYF(0), "Failed to flush relay info file.");
10797 1 goto err;
10798 }
10799
10800 } /* end 'if (thread_mask & SLAVE_SQL == 0)' */
10801
10802
1/2
✓ Branch 0 taken 12634 times.
✗ Branch 1 not taken.
12634 log_invalid_position_warning(thd, lex_mi, mi);
10803
10804
2/2
✓ Branch 0 taken 11275 times.
✓ Branch 1 taken 1359 times.
12634 if (mta_remove_worker_info)
10805
3/4
✓ Branch 0 taken 1359 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1358 times.
1359 if (Rpl_info_factory::reset_workers(mi->rli)) {
10806 1 error = ER_MTS_RESET_WORKERS;
10807
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_MTS_RESET_WORKERS, MYF(0));
10808 1 goto err;
10809 }
10810 11275 err:
10811
10812
1/2
✓ Branch 0 taken 12785 times.
✗ Branch 1 not taken.
12785 unlock_slave_threads(mi);
10813
1/2
✓ Branch 0 taken 12785 times.
✗ Branch 1 not taken.
12785 mi->channel_unlock();
10814 12785 return error;
10815 12785 }
10816
10817 /**
10818 This function is first called when the Master_info object
10819 corresponding to a channel in a multisourced slave does not
10820 exist. But before a new channel is created, certain
10821 conditions have to be met. The below function apriorily
10822 checks if all such conditions are met. If all the
10823 conditions are met then it creates a channel i.e
10824 mi<->rli
10825
10826 @param[in,out] mi When new {mi,rli} are created,
10827 the reference is stored in *mi
10828 @param[in] channel The channel on which the change
10829 master was introduced.
10830 */
10831 3795 int add_new_channel(Master_info **mi, const char *channel) {
10832
1/2
✓ Branch 0 taken 3795 times.
✗ Branch 1 not taken.
3795 DBUG_TRACE;
10833
10834 3795 int error = 0;
10835 Ident_name_check ident_check_status;
10836
10837 /*
10838 Refuse to create a new channel if the repositories does not support this.
10839 */
10840
10841
2/2
✓ Branch 0 taken 3793 times.
✓ Branch 1 taken 2 times.
3795 if (opt_mi_repository_id == INFO_REPOSITORY_FILE ||
10842
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3792 times.
3793 opt_rli_repository_id == INFO_REPOSITORY_FILE) {
10843
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(ERROR_LEVEL,
10844 ER_RPL_SLAVE_NEW_MASTER_INFO_NEEDS_REPOS_TYPE_OTHER_THAN_FILE);
10845 3 error = ER_SLAVE_NEW_CHANNEL_WRONG_REPOSITORY;
10846
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_SLAVE_NEW_CHANNEL_WRONG_REPOSITORY, MYF(0));
10847 3 goto err;
10848 }
10849
10850 /*
10851 Return if max num of replication channels exceeded already.
10852 */
10853
10854
3/4
✓ Branch 0 taken 3792 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3791 times.
3792 if (!channel_map.is_valid_channel_count()) {
10855 1 error = ER_SLAVE_MAX_CHANNELS_EXCEEDED;
10856
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SLAVE_MAX_CHANNELS_EXCEEDED, MYF(0));
10857 1 goto err;
10858 }
10859
10860 /*
10861 Now check the sanity of the channel name. It's length etc. The channel
10862 identifier is similar to table names. So, use check_table_function.
10863 */
10864
1/2
✓ Branch 0 taken 3791 times.
✗ Branch 1 not taken.
3791 if (channel) {
10865
1/2
✓ Branch 0 taken 3791 times.
✗ Branch 1 not taken.
3791 ident_check_status = check_table_name(channel, strlen(channel));
10866 } else
10867 ident_check_status = Ident_name_check::WRONG;
10868
10869
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3788 times.
3791 if (ident_check_status != Ident_name_check::OK) {
10870 3 error = ER_SLAVE_CHANNEL_NAME_INVALID_OR_TOO_LONG;
10871
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_SLAVE_CHANNEL_NAME_INVALID_OR_TOO_LONG, MYF(0));
10872 3 goto err;
10873 }
10874
10875
3/4
✓ Branch 0 taken 3788 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3787 times.
✓ Branch 3 taken 1 times.
3788 if (!((*mi) = Rpl_info_factory::create_mi_and_rli_objects(
10876 opt_mi_repository_id, opt_rli_repository_id, channel, false,
10877 &channel_map))) {
10878 1 error = ER_MASTER_INFO;
10879
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_MASTER_INFO, MYF(0));
10880 1 goto err;
10881 }
10882
10883 3787 err:
10884
10885 3795 return error;
10886 3795 }
10887
10888 /**
10889 Method used to check if the user is trying to update any other option for
10890 the change master apart from the MASTER_USER and MASTER_PASSWORD.
10891 In case user tries to update any other parameter apart from these two,
10892 this method will return error.
10893
10894 @param lex_mi structure that holds all change master options given on
10895 the change master command.
10896
10897 @retval true - The CHANGE MASTER is updating a unsupported parameter for the
10898 recovery channel.
10899
10900 @retval false - Everything is fine. The CHANGE MASTER can execute with the
10901 given option(s) for the recovery channel.
10902 */
10903 1872 static bool is_invalid_change_master_for_group_replication_recovery(
10904 const LEX_MASTER_INFO *lex_mi) {
10905
1/2
✓ Branch 0 taken 1872 times.
✗ Branch 1 not taken.
1872 DBUG_TRACE;
10906 1872 bool have_extra_option_received = false;
10907
10908 /* Check if *at least one* receive/execute option is given on change master
10909 * command*/
10910
4/6
✓ Branch 0 taken 1870 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1870 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1870 times.
✗ Branch 5 not taken.
1872 if (lex_mi->host || lex_mi->log_file_name || lex_mi->pos ||
10911
4/6
✓ Branch 0 taken 1870 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1869 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1869 times.
✗ Branch 5 not taken.
1870 lex_mi->bind_addr || lex_mi->port || lex_mi->connect_retry ||
10912
1/2
✓ Branch 0 taken 1869 times.
✗ Branch 1 not taken.
1869 lex_mi->server_id ||
10913
2/2
✓ Branch 0 taken 1867 times.
✓ Branch 1 taken 2 times.
1869 lex_mi->auto_position != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10914
1/2
✓ Branch 0 taken 1867 times.
✗ Branch 1 not taken.
1867 lex_mi->ssl != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10915
1/2
✓ Branch 0 taken 1867 times.
✗ Branch 1 not taken.
1867 lex_mi->ssl_verify_server_cert != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10916
1/2
✓ Branch 0 taken 1867 times.
✗ Branch 1 not taken.
1867 lex_mi->heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10917
1/2
✓ Branch 0 taken 1867 times.
✗ Branch 1 not taken.
1867 lex_mi->retry_count_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10918
3/6
✓ Branch 0 taken 1867 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1867 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1867 times.
✗ Branch 5 not taken.
1867 lex_mi->ssl_key || lex_mi->ssl_cert || lex_mi->ssl_ca ||
10919
2/4
✓ Branch 0 taken 1867 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1867 times.
✗ Branch 3 not taken.
1867 lex_mi->ssl_capath || lex_mi->tls_version ||
10920
2/2
✓ Branch 0 taken 1866 times.
✓ Branch 1 taken 1 times.
1867 lex_mi->tls_ciphersuites != LEX_MASTER_INFO::UNSPECIFIED ||
10921
3/6
✓ Branch 0 taken 1866 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1866 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1866 times.
✗ Branch 5 not taken.
1866 lex_mi->ssl_cipher || lex_mi->ssl_crl || lex_mi->ssl_crlpath ||
10922
1/2
✓ Branch 0 taken 1866 times.
✗ Branch 1 not taken.
1866 lex_mi->repl_ignore_server_ids_opt == LEX_MASTER_INFO::LEX_MI_ENABLE ||
10923
2/4
✓ Branch 0 taken 1866 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1866 times.
✗ Branch 3 not taken.
1866 lex_mi->relay_log_name || lex_mi->relay_log_pos ||
10924
2/4
✓ Branch 0 taken 1866 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1866 times.
✗ Branch 3 not taken.
1866 lex_mi->sql_delay != -1 || lex_mi->public_key_path ||
10925
1/2
✓ Branch 0 taken 1866 times.
✗ Branch 1 not taken.
1866 lex_mi->get_public_key != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10926
2/4
✓ Branch 0 taken 1866 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1866 times.
✗ Branch 3 not taken.
1866 lex_mi->zstd_compression_level || lex_mi->compression_algorithm ||
10927
2/2
✓ Branch 0 taken 1864 times.
✓ Branch 1 taken 2 times.
1866 lex_mi->require_row_format != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10928
2/2
✓ Branch 0 taken 1863 times.
✓ Branch 1 taken 1 times.
1864 lex_mi->m_source_connection_auto_failover !=
10929 1863 LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10930
1/2
✓ Branch 0 taken 1863 times.
✗ Branch 1 not taken.
1863 lex_mi->assign_gtids_to_anonymous_transactions_type !=
10931 1863 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UNCHANGED ||
10932
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1861 times.
1863 lex_mi->m_gtid_only != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
10933 11 have_extra_option_received = true;
10934
10935 1872 return have_extra_option_received;
10936 1872 }
10937
10938 /**
10939 Method used to check if the user is trying to update any other option for
10940 the change master apart from the PRIVILEGE_CHECKS_USER.
10941 In case user tries to update any other parameter apart from this one, this
10942 method will return error.
10943
10944 @param lex_mi structure that holds all change master options given on
10945 the change master command.
10946
10947 @retval true - The CHANGE MASTER is updating a unsupported parameter for the
10948 recovery channel.
10949
10950 @retval false - Everything is fine. The CHANGE MASTER can execute with the
10951 given option(s) for the recovery channel.
10952 */
10953 20 static bool is_invalid_change_master_for_group_replication_applier(
10954 const LEX_MASTER_INFO *lex_mi) {
10955
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 DBUG_TRACE;
10956 20 bool have_extra_option_received = false;
10957
10958 /* Check if *at least one* receive/execute option is given on change master
10959 * command*/
10960
4/6
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
20 if (lex_mi->host || lex_mi->user || lex_mi->password ||
10961
3/6
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
17 lex_mi->log_file_name || lex_mi->pos || lex_mi->bind_addr ||
10962
3/6
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
17 lex_mi->port || lex_mi->connect_retry || lex_mi->server_id ||
10963
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2 times.
17 lex_mi->auto_position != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10964
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 lex_mi->ssl != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10965
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 lex_mi->ssl_verify_server_cert != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10966
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 lex_mi->heartbeat_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10967
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 lex_mi->retry_count_opt != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10968
3/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
15 lex_mi->ssl_key || lex_mi->ssl_cert || lex_mi->ssl_ca ||
10969
3/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
15 lex_mi->ssl_capath || lex_mi->tls_version || lex_mi->ssl_cipher ||
10970
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 lex_mi->ssl_crl || lex_mi->ssl_crlpath ||
10971
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 lex_mi->repl_ignore_server_ids_opt == LEX_MASTER_INFO::LEX_MI_ENABLE ||
10972
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 lex_mi->relay_log_name || lex_mi->relay_log_pos ||
10973
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 lex_mi->sql_delay != -1 || lex_mi->public_key_path ||
10974
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 lex_mi->get_public_key != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10975
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 lex_mi->zstd_compression_level || lex_mi->compression_algorithm ||
10976
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2 times.
15 lex_mi->require_row_format != LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10977
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
13 lex_mi->m_source_connection_auto_failover !=
10978 11 LEX_MASTER_INFO::LEX_MI_UNCHANGED ||
10979
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 lex_mi->assign_gtids_to_anonymous_transactions_type !=
10980 11 LEX_MASTER_INFO::LEX_MI_ANONYMOUS_TO_GTID_UNCHANGED ||
10981
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 lex_mi->m_gtid_only != LEX_MASTER_INFO::LEX_MI_UNCHANGED)
10982 11 have_extra_option_received = true;
10983
10984 20 return have_extra_option_received;
10985 20 }
10986
10987 /**
10988 Entry point for the CHANGE MASTER command. Function
10989 decides to create a new channel or create an existing one.
10990
10991 @param[in] thd the client thread that issued the command.
10992
10993 @retval true fail
10994 @retval false success.
10995 */
10996 8050 bool change_master_cmd(THD *thd) {
10997
1/2
✓ Branch 0 taken 8050 times.
✗ Branch 1 not taken.
8050 DBUG_TRACE;
10998
10999 8050 Master_info *mi = nullptr;
11000 8050 LEX *lex = thd->lex;
11001 8050 bool res = false;
11002
11003
1/2
✓ Branch 0 taken 8050 times.
✗ Branch 1 not taken.
8050 channel_map.wrlock();
11004
11005 /* The slave must have been initialized to allow CHANGE MASTER statements */
11006
3/4
✓ Branch 0 taken 8050 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 8040 times.
8050 if (!is_slave_configured()) {
11007
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 my_error(ER_SLAVE_CONFIGURATION, MYF(0));
11008 10 res = true;
11009 10 goto err;
11010 }
11011
11012
3/4
✓ Branch 0 taken 8040 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 8020 times.
8040 if (channel_map.is_group_replication_channel_name(lex->mi.channel, true)) {
11013 /*
11014 If the chosen name is for group_replication_applier channel we allow the
11015 channel creation based on the check as to which field is being updated.
11016 */
11017 20 LEX_MASTER_INFO *lex_mi = &thd->lex->mi;
11018
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 9 times.
20 if (is_invalid_change_master_for_group_replication_applier(lex_mi)) {
11019
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
11020 "CHANGE MASTER with the given parameters", lex->mi.channel);
11021 11 res = true;
11022 11 goto err;
11023 }
11024
11025 /*
11026 group_replication_applier channel only has the SQL thread, the IO thread
11027 job is done by GR pipeline, which queues events into the relay log after
11028 going through certification.
11029 Thence for CHANGE MASTER execution pre-conditions we need to check if
11030 the full GR stack is stopped.
11031 */
11032
3/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 8 times.
9 if (is_group_replication_running()) {
11033
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_GRP_OPERATION_NOT_ALLOWED_GR_MUST_STOP, MYF(0));
11034 1 res = true;
11035 1 goto err;
11036 }
11037 }
11038
11039 // If the channel being used is group_replication_recovery we allow the
11040 // channel creation based on the check as to which field is being updated.
11041
5/6
✓ Branch 0 taken 8028 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1880 times.
✓ Branch 3 taken 6148 times.
✓ Branch 4 taken 1872 times.
✓ Branch 5 taken 6156 times.
9908 if (channel_map.is_group_replication_channel_name(lex->mi.channel) &&
11042
3/4
✓ Branch 0 taken 1880 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1872 times.
✓ Branch 3 taken 8 times.
1880 !channel_map.is_group_replication_channel_name(lex->mi.channel, true)) {
11043 1872 LEX_MASTER_INFO *lex_mi = &thd->lex->mi;
11044
3/4
✓ Branch 0 taken 1872 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 1861 times.
1872 if (is_invalid_change_master_for_group_replication_recovery(lex_mi)) {
11045
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
11046 "CHANGE MASTER with the given parameters", lex->mi.channel);
11047 11 res = true;
11048 11 goto err;
11049 }
11050 }
11051
11052 /*
11053 Error out if number of replication channels are > 1 if FOR CHANNEL
11054 clause is not provided in the CHANGE MASTER command.
11055 */
11056
7/8
✓ Branch 0 taken 1726 times.
✓ Branch 1 taken 6291 times.
✓ Branch 2 taken 1726 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 1722 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 8013 times.
8017 if (!lex->mi.for_channel && channel_map.get_num_instances() > 1) {
11057
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_SLAVE_MULTIPLE_CHANNELS_CMD, MYF(0));
11058 4 res = true;
11059 4 goto err;
11060 }
11061
11062 /* Get the Master_info of the channel */
11063
1/2
✓ Branch 0 taken 8013 times.
✗ Branch 1 not taken.
8013 mi = channel_map.get_mi(lex->mi.channel);
11064
11065 /* create a new channel if doesn't exist */
11066
5/6
✓ Branch 0 taken 2202 times.
✓ Branch 1 taken 5811 times.
✓ Branch 2 taken 2202 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2202 times.
✓ Branch 5 taken 5811 times.
8013 if (!mi && strcmp(lex->mi.channel, channel_map.get_default_channel())) {
11067 /* The mi will be returned holding mi->channel_lock for writing */
11068
3/4
✓ Branch 0 taken 2202 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 2194 times.
2202 if (add_new_channel(&mi, lex->mi.channel)) goto err;
11069 }
11070
11071
1/2
✓ Branch 0 taken 8005 times.
✗ Branch 1 not taken.
8005 if (mi) {
11072 8005 bool configure_filters = !Master_info::is_configured(mi);
11073
11074
3/4
✓ Branch 0 taken 8005 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7855 times.
✓ Branch 3 taken 150 times.
8005 if (!(res = change_master(thd, mi, &thd->lex->mi))) {
11075 /*
11076 If the channel was just created or not configured before this
11077 "CHANGE MASTER", we need to configure rpl_filter for it.
11078 */
11079
2/2
✓ Branch 0 taken 5441 times.
✓ Branch 1 taken 2414 times.
7855 if (configure_filters) {
11080
3/4
✓ Branch 0 taken 5441 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 5434 times.
5441 if ((res = Rpl_info_factory::configure_channel_replication_filters(
11081 mi->rli, lex->mi.channel)))
11082 7 goto err;
11083 }
11084
11085 /*
11086 Issuing deprecation warnings after the change (we make
11087 sure that we don't issue warning if there is an error).
11088 */
11089
1/2
✓ Branch 0 taken 7848 times.
✗ Branch 1 not taken.
7848 issue_deprecation_warnings_for_channel(thd);
11090
11091
1/2
✓ Branch 0 taken 7848 times.
✗ Branch 1 not taken.
7848 my_ok(thd);
11092 }
11093 } else {
11094 /*
11095 Even default channel does not exist. So issue a previous
11096 backward compatible error message (till 5.6).
11097 @TODO: This error message shall be improved.
11098 */
11099 my_error(ER_SLAVE_CONFIGURATION, MYF(0));
11100 }
11101
11102 8050 err:
11103
1/2
✓ Branch 0 taken 8050 times.
✗ Branch 1 not taken.
8050 channel_map.unlock();
11104
11105 8050 return res;
11106 8050 }
11107
11108 /**
11109 Check if there is any slave SQL config conflict.
11110
11111 @param[in] rli The slave's rli object.
11112
11113 @return 0 is returned if there is no conflict, otherwise 1 is returned.
11114 */
11115 21715 static int check_slave_sql_config_conflict(const Relay_log_info *rli) {
11116 int channel_mts_submode, replica_parallel_workers;
11117
11118
2/2
✓ Branch 0 taken 10321 times.
✓ Branch 1 taken 11394 times.
21715 if (rli) {
11119 10321 channel_mts_submode = rli->channel_mts_submode;
11120 10321 replica_parallel_workers = rli->opt_replica_parallel_workers;
11121 } else {
11122 /*
11123 When the slave is first initialized, we collect the values from the
11124 command line options
11125 */
11126 11394 channel_mts_submode = mts_parallel_option;
11127 11394 replica_parallel_workers = opt_mts_replica_parallel_workers;
11128 }
11129
11130
4/4
✓ Branch 0 taken 21534 times.
✓ Branch 1 taken 181 times.
✓ Branch 2 taken 21483 times.
✓ Branch 3 taken 51 times.
21715 if (opt_replica_preserve_commit_order && replica_parallel_workers > 0) {
11131
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 21480 times.
21483 if (channel_mts_submode == MTS_PARALLEL_TYPE_DB_NAME) {
11132 3 my_error(ER_DONT_SUPPORT_REPLICA_PRESERVE_COMMIT_ORDER, MYF(0),
11133 "when replica_parallel_type is DATABASE");
11134 3 return ER_DONT_SUPPORT_REPLICA_PRESERVE_COMMIT_ORDER;
11135 }
11136 }
11137
11138
2/2
✓ Branch 0 taken 10318 times.
✓ Branch 1 taken 11394 times.
21712 if (rli) {
11139 10318 const char *channel = const_cast<Relay_log_info *>(rli)->get_channel();
11140
2/2
✓ Branch 0 taken 10231 times.
✓ Branch 1 taken 44 times.
10275 if (replica_parallel_workers > 0 &&
11141
1/2
✓ Branch 0 taken 10231 times.
✗ Branch 1 not taken.
10231 (channel_mts_submode != MTS_PARALLEL_TYPE_LOGICAL_CLOCK ||
11142 10231 (channel_mts_submode == MTS_PARALLEL_TYPE_LOGICAL_CLOCK &&
11143
6/6
✓ Branch 0 taken 10275 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 95 times.
✓ Branch 3 taken 10136 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 10315 times.
20688 !opt_replica_preserve_commit_order)) &&
11144
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 136 times.
139 channel_map.is_group_replication_channel_name(channel, true)) {
11145 3 my_error(ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED, MYF(0),
11146 "START SLAVE SQL_THREAD when REPLICA_PARALLEL_WORKERS > 0 "
11147 "and REPLICA_PARALLEL_TYPE != LOGICAL_CLOCK "
11148 "or REPLICA_PRESERVE_COMMIT_ORDER != ON",
11149 channel);
11150 3 return ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED;
11151 }
11152 }
11153
11154 21709 return 0;
11155 }
11156
11157 /**
11158 Purge Group Replication channels relay logs after this server being a
11159 recipient of clone.
11160 */
11161 11394 static void group_replication_cleanup_after_clone() {
11162
5/6
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 11344 times.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 11344 times.
11394 if (clone_startup && get_server_state() == SERVER_BOOTING) {
11163
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 channel_map.assert_some_wrlock();
11164
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 Auto_THD thd;
11165
11166
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 Master_info *mi = channel_map.get_mi("group_replication_applier");
11167
3/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
50 if (nullptr != mi) reset_slave(thd.thd, mi, false);
11168
11169
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 mi = channel_map.get_mi("group_replication_recovery");
11170
3/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
50 if (nullptr != mi) reset_slave(thd.thd, mi, false);
11171 50 }
11172 11394 }
11173
11174 /**
11175 @} (end of group Replication)
11176 */
11177
11178 /**
11179 Checks the current replica configuration against the server GTID mode
11180 If some incompatibility is found a warning is logged.
11181 */
11182 11394 static void check_replica_configuration_restrictions() {
11183
1/2
✓ Branch 0 taken 11394 times.
✗ Branch 1 not taken.
11394 std::string group_name = get_group_replication_group_name();
11184
7/8
✓ Branch 0 taken 11394 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2198 times.
✓ Branch 3 taken 9196 times.
✓ Branch 4 taken 187 times.
✓ Branch 5 taken 2011 times.
✓ Branch 6 taken 9383 times.
✓ Branch 7 taken 2011 times.
11394 if (global_gtid_mode.get() != Gtid_mode::ON || group_name.length() > 0) {
11185
5/8
✓ Branch 0 taken 9383 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9383 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9423 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9423 times.
✓ Branch 7 taken 9383 times.
18806 for (auto it : channel_map) {
11186 9423 Master_info *mi = it.second;
11187
1/2
✓ Branch 0 taken 9423 times.
✗ Branch 1 not taken.
9423 if (mi != nullptr) {
11188
3/4
✓ Branch 0 taken 9423 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9229 times.
✓ Branch 3 taken 194 times.
9423 if (global_gtid_mode.get() != Gtid_mode::ON) {
11189 // Check if a channel has SOURCE_AUTO POSITION
11190
7/8
✓ Branch 0 taken 9229 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9224 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 9221 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 9226 times.
18453 if (global_gtid_mode.get() == Gtid_mode::OFF &&
11191 9224 mi->is_auto_position()) {
11192
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(WARNING_LEVEL,
11193 ER_RPL_SLAVE_AUTO_POSITION_IS_1_AND_GTID_MODE_IS_OFF,
11194 mi->get_channel(), mi->get_channel());
11195 }
11196 // Check if a channel has SOURCE_CONNECTION_AUTO_FAILOVER
11197
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9226 times.
9229 if (mi->is_source_connection_auto_failover()) {
11198
8/16
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 LogErr(WARNING_LEVEL, ER_RPL_ASYNC_RECONNECT_GTID_MODE_OFF_CHANNEL,
11199 mi->get_channel(), mi->get_channel());
11200 }
11201 // Check if a channel has GTID_ONLY
11202
3/4
✓ Branch 0 taken 9229 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 9228 times.
9229 if (mi->is_gtid_only_mode()) {
11203
8/16
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
1 LogErr(WARNING_LEVEL,
11204 ER_WARN_REPLICA_GTID_ONLY_AND_GTID_MODE_NOT_ON,
11205 mi->get_channel());
11206 }
11207 // Check if a channel has ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
11208 18458 if (mi->rli->m_assign_gtids_to_anonymous_transactions_info
11209
3/4
✓ Branch 0 taken 9229 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9227 times.
9229 .get_type() > Assign_gtids_to_anonymous_transactions_info::
11210 enum_type::AGAT_OFF) {
11211 2 std::string assign_gtid_type;
11212 4 if (mi->rli->m_assign_gtids_to_anonymous_transactions_info
11213
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 .get_type() == Assign_gtids_to_anonymous_transactions_info::
11214 enum_type::AGAT_LOCAL)
11215
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 assign_gtid_type.assign("LOCAL");
11216 else
11217 assign_gtid_type.assign("a UUID");
11218
10/20
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
2 LogErr(
11219 WARNING_LEVEL,
11220 ER_SLAVE_ANONYMOUS_TO_GTID_IS_LOCAL_OR_UUID_AND_GTID_MODE_NOT_ON,
11221 mi->get_channel(), assign_gtid_type.data(),
11222 Gtid_mode::to_string(global_gtid_mode.get()));
11223 2 }
11224 } else {
11225 // No checks needed if mode is OFF
11226 574 if (mi->rli->m_assign_gtids_to_anonymous_transactions_info
11227
3/4
✓ Branch 0 taken 194 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 186 times.
✓ Branch 3 taken 8 times.
194 .get_type() ==
11228 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF)
11229 186 continue;
11230
11231 /*
11232 Check if one of the channels with
11233 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
11234 does not have the same UUID as Group Replication
11235 */
11236
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (!(group_name.compare(
11237 8 mi->rli->m_assign_gtids_to_anonymous_transactions_info
11238
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
16 .get_value()))) {
11239
9/18
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
2 LogErr(WARNING_LEVEL,
11240 ER_REPLICA_ANONYMOUS_TO_GTID_UUID_SAME_AS_GROUP_NAME,
11241 mi->get_channel(),
11242 mi->rli->m_assign_gtids_to_anonymous_transactions_info
11243 .get_value()
11244 .c_str());
11245 }
11246 /*
11247 Check if one of the channels with
11248 ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS
11249 does not have the same UUID as group_replication_view_change_uuid
11250 */
11251 8 std::string view_change_uuid;
11252
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (get_group_replication_view_change_uuid(view_change_uuid)) {
11253 /* purecov: begin inspected */
11254 LogErr(WARNING_LEVEL,
11255 ER_WARN_GRP_RPL_VIEW_CHANGE_UUID_FAIL_GET_VARIABLE);
11256 /* purecov: end */
11257 }
11258
11259
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (!(view_change_uuid.compare(
11260 8 mi->rli->m_assign_gtids_to_anonymous_transactions_info
11261
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
16 .get_value()))) {
11262
9/18
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
1 LogErr(
11263 WARNING_LEVEL,
11264 ER_WARN_REPLICA_ANONYMOUS_TO_GTID_UUID_SAME_AS_VIEW_CHANGE_UUID,
11265 mi->get_channel(),
11266 mi->rli->m_assign_gtids_to_anonymous_transactions_info
11267 .get_value()
11268 .c_str());
11269 }
11270 8 }
11271 }
11272
2/2
✓ Branch 0 taken 9237 times.
✓ Branch 1 taken 186 times.
9423 }
11273 }
11274 11394 }
11275
11276 /**
11277 Checks the current replica configuration when starting a replication thread
11278 If some incompatibility is found an error is thrown.
11279
11280 @param mi pointer to the source info repository object
11281 @param thread_mask what replication threads are running
11282
11283 @return true if an error occurs, false otherwise
11284 */
11285 11158 static bool check_replica_configuration_errors(Master_info *mi,
11286 int thread_mask) {
11287
2/2
✓ Branch 0 taken 6095 times.
✓ Branch 1 taken 5063 times.
11158 if (global_gtid_mode.get() != Gtid_mode::ON) {
11288
5/6
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 6064 times.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 6092 times.
6126 if (mi->is_auto_position() && (thread_mask & SLAVE_IO) &&
11289
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 28 times.
31 global_gtid_mode.get() == Gtid_mode::OFF) {
11290 3 my_error(ER_CANT_USE_AUTO_POSITION_WITH_GTID_MODE_OFF, MYF(0),
11291 3 mi->get_for_channel_str());
11292 3 return true;
11293 }
11294
11295
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6089 times.
6092 if (mi->is_source_connection_auto_failover()) {
11296 3 my_error(ER_RPL_ASYNC_RECONNECT_GTID_MODE_OFF, MYF(0));
11297 3 return true;
11298 }
11299
11300
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6088 times.
6089 if (mi->is_gtid_only_mode()) {
11301 1 my_error(ER_CANT_USE_GTID_ONLY_WITH_GTID_MODE_NOT_ON, MYF(0),
11302 1 mi->get_for_channel_str());
11303 1 return true;
11304 }
11305
11306
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6087 times.
6088 if ((mi->rli->m_assign_gtids_to_anonymous_transactions_info.get_type() >
11307 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF)) {
11308 /*
11309 This function may be called either during server start (when
11310 --skip-start-replica is not used) or during START SLAVE. The error
11311 should only be generated during START SLAVE. During server start, an
11312 error has already been written to the log for this case (in
11313 init_replica).
11314 */
11315
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (current_thd)
11316 1 my_error(ER_CANT_USE_ANONYMOUS_TO_GTID_WITH_GTID_MODE_NOT_ON, MYF(0),
11317 1 mi->get_for_channel_str());
11318 1 return true;
11319 }
11320 }
11321
11322
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 11116 times.
11150 if (mi->rli->m_assign_gtids_to_anonymous_transactions_info.get_type() >
11323 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF) {
11324
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 std::string group_name = get_group_replication_group_name();
11325
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 26 times.
42 if ((group_name.length() > 0) &&
11326
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
8 !(group_name.compare(
11327 8 mi->rli->m_assign_gtids_to_anonymous_transactions_info
11328
5/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 26 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
42 .get_value()))) {
11329
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_ANONYMOUS_TO_GTID_UUID_SAME_AS_GROUP_NAME, MYF(0),
11330 mi->get_channel());
11331 2 return true;
11332 }
11333 32 std::string view_change_uuid;
11334
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
32 if (get_group_replication_view_change_uuid(view_change_uuid)) {
11335 /* purecov: begin inspected */
11336 my_error(ER_GRP_RPL_VIEW_CHANGE_UUID_FAIL_GET_VARIABLE, MYF(0));
11337 return true;
11338 /* purecov: end */
11339 } else {
11340
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (!(view_change_uuid.compare(
11341 32 mi->rli->m_assign_gtids_to_anonymous_transactions_info
11342
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 31 times.
64 .get_value()))) {
11343
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_ANONYMOUS_TO_GTID_UUID_SAME_AS_VIEW_CHANGE_UUID, MYF(0),
11344 mi->get_channel());
11345 1 return true;
11346 }
11347 }
11348
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 1 times.
31 if (mi->rli->until_condition == Relay_log_info::UNTIL_SQL_BEFORE_GTIDS ||
11349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 mi->rli->until_condition == Relay_log_info::UNTIL_SQL_AFTER_GTIDS) {
11350
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_CANT_SET_SQL_AFTER_OR_BEFORE_GTIDS_WITH_ANONYMOUS_TO_GTID,
11351 MYF(0));
11352 1 return true;
11353 }
11354
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 4 times.
36 }
11355 11146 return false;
11356 }
11357